I think I cautiously agree with this notion to some extent, but IMHO the real answer is that it's application-dependent, and if you're writing a low-level trig library and you have to pick one or the other, it really isn't clear to me that turns should win over radians.
I expect many systems that use trigonometry would sometimes use small-angle approximations either for efficiency or to bootstrap to the general case. It'd be natural to use Taylor series here, i.e.:
cos(x) = 1 - x^2/2 + ...
sin(x) = x - x^3/6 + ...
If you've committed to representing all trigonometry in "turn" units, then you instead need to use:
cos(2 pi t) = 1 - (2 pi t)^2/2 + ...
sin(2 pi t) = (2 pi t) - (2 pi t)^3/6 + ...
In this case it would be less accurate and efficient to force everything into turns if you ever need to work with radians.
Closely related to this, if you ever need the derivative of a function that does trig (e.g., in numerical optimization), you may as well use radians because if you don't, any extra factors you apply will appear in the expressions for the derivatives and you'll have to deal with them there anyway.
Basically for that reason, it's pretty clear that trigonometry in terms of radians is the "correct" convention mathematically speaking (away from computers), since derivatives of the radian-based trig functions are so easy to express. Given that, if we have to pick one convention...isn't it less confusing to use the same thing everywhere? That said, there are interfaces that provide both versions, and since as the article points out there are cases where the turn-based versions can be more efficient, that's probably the right way to go.
I don't have a super-wide gamut of experience here and numerical analysis isn't my specialty, but nearly all trig implementations I've looked into (in both software and hardware) make heavy use of lookup tables and other shortcuts. I've never seen a Taylor series used in a general implementation - not saying it doesn't exist anywhere, but in most cases that I'm familiar with you could support turns just as easily with a different lookup table.
If you're being technical, it's usually not a Taylor series, it's a minimax series. (The difference is that Taylor series minimize error at a given value, whereas minimax is trying to minimize maximum error in a range).
Of course, if you're not using a standard math library implementation, you're probably preferring speed over accuracy, and so you might use a lookup table and linear interpolation to get a very coarse approximation instead.
Very bold title! Turns are very convenient until you need to calculate a rate of change, as of course d/dx sin(2pi x) = 2pi cos(2pi x). Unfortunately this is a common enough problem that I will be sticking with the radian.
I feel like that approximates how I learned math. In geometry or trig you can use degrees or turns or any other unit, but almost never radians because that's harder write. As soon as you learn calculus, you switch to radians and never go back.
I like to store angles as turns in my own code, because (as noted) it makes quarter-turns computable without rounding. OTOH if you need, say, twelfths of a turn, you might want to just store angles as degrees since that’s already common.
Michael Spivak, in Calculus (3rd ed p. 301) considers the unit choice to be a property of the function and initially defines sin° and sinʳ (before settling on sin meaning sinʳ) and considers “sin x°” and “sin x radians” to be misleading, saying that ‘a number x is simply a number—it does not carry a banner indicating that it is “in degrees” or “in radians”’. I don’t really understand this argument, since in science and engineering we constantly carry units around with our quantities.
It's because both radians and degrees are are a ratio of a length to another length and are thus dimensionless. No matter how you measure it, all angles are without a unit.
It's most obvious with radians but it's also the case with degrees.
Using radians, you are guaranteed to not introduce unusual extra terms to rescale angles, if you use any other scale of angle you will have to keep track of extra terms.
That may be useful in whatever you're doing. I work in degrees quite often and I'm careful to keep track of the 2pi/360 terms that crop up all over the place. With grade measure you have to keep track of 2pi/400 terms and with turns you have to keep track of 2pi/1 terms that will repeatedly show up.
Again, depending on what you're doing, this may or may not make sense to do.
In general, mathematics works out easier when the scaling term is 2pi/2pi because then you have a lovely 1 scale factor you don't have to keep track of.
You generally can’t apply functions to dimensional units. The only thing units can do is be multiplied or divided together. So I can multiply a mass by a distance or divide a distance by a speed, and I can multiply the result by a scalar; but I can’t take the sine of a distance or the logarithm of a time or exponentiate a mass. Those are things I can only do to scalars.
‘But wait!’ You may cry: ‘the formula for a transverse wave varies with the sine of a distance!’
To which I would say no: it varies with the sine of a distance (the horizontal displacement), divided by another distance (the wavelength), divided by 2pi. The distances cancel out and leave a scalar. The sine is taken of that pure scalar; it results in a pure scalar; and then it’s multiplied by another distance (the amplitude) to give you a vertical displacement. Sine is a pure function.
Something else to consider is that the way we combine units with scalars to create dimensional quantities is through multiplication - and it’s not like there’s a simple formula for what a sine of a product is - I can’t determine sin(ab) in terms of sines or other functions of a and b. So if, say, a ‘degree’ were some dimensional unit, sin(90°) would not be something I could calculate - despite knowing sin(90) I don’t know sin(°) - whatever that would mean - and even if I did it gets me no closer to figuring out sin(90°)
Realizing that ° is just a mathematical constant equal to pi/180 solves a lot here.
> But math never decreed that sine and cosine have to take radian arguments!
If you don't use radians you have to add to add conversion factors everywhere to do calculus. Radians are the natural unit for sin/cos just as E is the natural base of the logarithm and exponential functions.
And could use fixed-point decimal for more efficiency since can store as integers and use integer hardware for them. So for instance with 32-bits, the 16 most-sig bits store the number of turns and the 16 least-significant bits store the fraction of a turn. Then if you want to wrap angles that exceed 360 degrees back around the circle, you can simply Logical_AND with 0x0000FFFF. And while you are at it, you could just use fixed-point decimal for sine and cos, whereby the maximum of +1 or -1 map to the most positive and most negative integer value. These type of optimizations were common before FPUs were cheap and fast.
The problem is that trigonometric functions are used in many more fields beyond geometry. The input is not always an angle around a point in euclidean space, it could be phase angle of a periodic signal. You can make an alternative set of trig functions that take turns, but you will anger a lot of people if you mess with the vanilla trig functions.
When dealing with waves you often are dealing with turns - or, as they’re called in that world, cycles. A cycle is a turn is tau is 2pi.
The SI unit for frequency after all is Hertz - cycles per second - which should really be considered equal to 2pi s^-1, but for complicated reasons, often isn’t, and most formulae that involve frequency ignore the ‘cycle’ - or it’s also hiding inside the definition of something like the wavelength or the Planck constant where it cancels out.
Meanwhile the SI unit for angular velocity is radians per second which is dimensionally equivalent to s^-1.
That said a becquerel, which measures rate of discrete events, is also dimensionally s^-1. (Next time you are measuring traffic to your website consider using the appropriate SI unit for measuring requests per second: the Becquerel.) - so dimensional equivalence isn’t the same as equivalence. You wouldn’t add a rate to a frequency, same as you probably shouldn’t add a torque to an amount of energy.
You'll have to bring in the 2π factor somewhere. Cant escape it. If sint is the sin function but with angle give in turns, then d/dx sint(x) = 2π cost(x). sin(x) ~ x for small x but sint(x) ~ 2πx for small x.
Yes, the idea of a turn [1] is interesting. And maybe useful.
I have a different question: What would it take for a compiler to remove (elide) the multiply by pi + divide by pi that the author uses as an example? I guess one would not have to go as far as a Lean proof that two bits of code produce the same result?
The short answer is you need fast-math flags to allow optimizations that may change floating-point results, and you also need to guarantee an implementation of sinpi/cospi (these were added in C23, so they're not all that common in host library implementations yet).
It's possible if you had the implementation of the math library visible to the compiler that it could do inlining and then simplify expressions, but honestly most math library function implementations are going to be the kind of function that doesn't get picked up by inline heuristics, as there's a pile of if statements (handling special cases and range reduction) that the compiler can't eliminate due to there not really existing a sufficiently powerful FP range analysis.
Well, they don't produce the same result in floating point math, I'm afraid.
So you'd need to teach your compiler about what your formulas mean and what context you are using them in. (Ie are you actually doing geometry, or is your AI coding agent just trying arbitrary activation functions for your neuronal net experiments and some of them happen to look like geometry?)
I think the point is that, from a compiler's perspective, it's not obvious how much you should be allowed to optimise code at the cost of changing the outcomes of floating points maths - do you allow 1e-10, or 1e-6, or 1e-4 level changes? Does your compiler have to run some test calcs to bound the scale of the change introduced by rewriting fp maths? Some compilers will let you opt in to rewriting floating point maths, but that's opt in so users understand that their numeric outputs might change between optimisation levels.
Huh, what? Floating point numbers have a standard, you know. They aren't non-deterministic YOLO numbers.
By default, the compiler has to stick to what the standard requires, and can't just say add arbitrary imprecision.
Your epsilon is what you get when you try to analyse floating point numbers as approximations of real numbers. But they also have an independent life as bit patterns, and the compiler can't just willy-nilly muck around with these bit patterns.
Please look at the link where context is clear here. Floating point has limited precision and the complete inability to exactly represent some numbers.
Example, this equality check is false:
0.1 + 0.2 == 0.3
Because the last bits of a floating point number, after any practical chain of operations, is practically random, do to errors from limited precision. Yes you can always know what the result will exactly be for any operation, if you know the exact number and operations used. Good luck with something like sin/cos though, where implementations can vary wildly depending on the platform/library.
Your problem only occurs when you try to naively transport equality of real numbers into equality of floating point numbers.
https://www.netlib.org/fp/dtoa.c is how eg CPython parses literals like 0.3 into floating point numbers. Lo and behold: that algorithm compares floating point number for equality, and would break catastrophically, if the compiler were allowed to willy-nilly fiddle with the bit patterns.
There are valid reasons to prefer radians, especially in calculus. The fact that it's related to arc length is something that never (directly) comes up.
Every part of calculus with trig functions relies on this fact! The rate of motion along a circle is approximately linear at the same speed when described in radians.
For example when you do a Taylor series expansion the cos/sin are well approximated by x.
That's why I put "directly" in my original post. All the nice functions in calculus rely on that fact, but that fact itself is almost never used or useful by itself .
If I were writing the article I would focus on the benefits for derivatives and integration and other things that are slipping my mind at the moment. I wouldn't waste time going down the rabbit hole of why.
At least not for an article aimed at this type of audience.
I think the author is either being disingenuous or doesn’t understand the subject if they don’t honestly address the reason radians are used in the first place. I’m leaning towards the latter, because I can’t imagine someone having an ulterior motive for pushing for trig reform like this, lol. Radians really are the natural unit for trigonometry. With that said, I certainly agree that a lot of code would be simplified by using turns over radians, especially outside the context of numerical methods. I could see myself supporting the addition of sint(x) and cost(x) functions to the math standard library, where sint = “sine turns”.
While not a strict rule, Chesterton’s fence is a good heuristic: before we change something, we should first attempt to understand why it is the way it is.
I expect many systems that use trigonometry would sometimes use small-angle approximations either for efficiency or to bootstrap to the general case. It'd be natural to use Taylor series here, i.e.:
If you've committed to representing all trigonometry in "turn" units, then you instead need to use: In this case it would be less accurate and efficient to force everything into turns if you ever need to work with radians.Closely related to this, if you ever need the derivative of a function that does trig (e.g., in numerical optimization), you may as well use radians because if you don't, any extra factors you apply will appear in the expressions for the derivatives and you'll have to deal with them there anyway.
Basically for that reason, it's pretty clear that trigonometry in terms of radians is the "correct" convention mathematically speaking (away from computers), since derivatives of the radian-based trig functions are so easy to express. Given that, if we have to pick one convention...isn't it less confusing to use the same thing everywhere? That said, there are interfaces that provide both versions, and since as the article points out there are cases where the turn-based versions can be more efficient, that's probably the right way to go.
In most general math library implementations (e.g., the library in glibc, musl, etc.), the implementation of sin, as with most functions, is going to be a polynomial evaluation. See, e.g., https://github.com/kraj/musl/blob/kraj/master/src/math/__cos... for the implementation in musl, or https://github.com/bminor/glibc/blob/master/sysdeps/ieee754/... for glibc's implementation.
Of course, if you're not using a standard math library implementation, you're probably preferring speed over accuracy, and so you might use a lookup table and linear interpolation to get a very coarse approximation instead.
Michael Spivak, in Calculus (3rd ed p. 301) considers the unit choice to be a property of the function and initially defines sin° and sinʳ (before settling on sin meaning sinʳ) and considers “sin x°” and “sin x radians” to be misleading, saying that ‘a number x is simply a number—it does not carry a banner indicating that it is “in degrees” or “in radians”’. I don’t really understand this argument, since in science and engineering we constantly carry units around with our quantities.
It's most obvious with radians but it's also the case with degrees.
Using radians, you are guaranteed to not introduce unusual extra terms to rescale angles, if you use any other scale of angle you will have to keep track of extra terms.
That may be useful in whatever you're doing. I work in degrees quite often and I'm careful to keep track of the 2pi/360 terms that crop up all over the place. With grade measure you have to keep track of 2pi/400 terms and with turns you have to keep track of 2pi/1 terms that will repeatedly show up.
Again, depending on what you're doing, this may or may not make sense to do.
In general, mathematics works out easier when the scaling term is 2pi/2pi because then you have a lovely 1 scale factor you don't have to keep track of.
But that's more for analysis of your code / formulas than when you actually go and compute things.
‘But wait!’ You may cry: ‘the formula for a transverse wave varies with the sine of a distance!’
To which I would say no: it varies with the sine of a distance (the horizontal displacement), divided by another distance (the wavelength), divided by 2pi. The distances cancel out and leave a scalar. The sine is taken of that pure scalar; it results in a pure scalar; and then it’s multiplied by another distance (the amplitude) to give you a vertical displacement. Sine is a pure function.
Something else to consider is that the way we combine units with scalars to create dimensional quantities is through multiplication - and it’s not like there’s a simple formula for what a sine of a product is - I can’t determine sin(ab) in terms of sines or other functions of a and b. So if, say, a ‘degree’ were some dimensional unit, sin(90°) would not be something I could calculate - despite knowing sin(90) I don’t know sin(°) - whatever that would mean - and even if I did it gets me no closer to figuring out sin(90°)
Realizing that ° is just a mathematical constant equal to pi/180 solves a lot here.
If you don't use radians you have to add to add conversion factors everywhere to do calculus. Radians are the natural unit for sin/cos just as E is the natural base of the logarithm and exponential functions.
The SI unit for frequency after all is Hertz - cycles per second - which should really be considered equal to 2pi s^-1, but for complicated reasons, often isn’t, and most formulae that involve frequency ignore the ‘cycle’ - or it’s also hiding inside the definition of something like the wavelength or the Planck constant where it cancels out.
Meanwhile the SI unit for angular velocity is radians per second which is dimensionally equivalent to s^-1.
That said a becquerel, which measures rate of discrete events, is also dimensionally s^-1. (Next time you are measuring traffic to your website consider using the appropriate SI unit for measuring requests per second: the Becquerel.) - so dimensional equivalence isn’t the same as equivalence. You wouldn’t add a rate to a frequency, same as you probably shouldn’t add a torque to an amount of energy.
I have a different question: What would it take for a compiler to remove (elide) the multiply by pi + divide by pi that the author uses as an example? I guess one would not have to go as far as a Lean proof that two bits of code produce the same result?
[1] https://en.wikipedia.org/wiki/Turn_(angle)
It's possible if you had the implementation of the math library visible to the compiler that it could do inlining and then simplify expressions, but honestly most math library function implementations are going to be the kind of function that doesn't get picked up by inline heuristics, as there's a pile of if statements (handling special cases and range reduction) that the compiler can't eliminate due to there not really existing a sufficiently powerful FP range analysis.
So you'd need to teach your compiler about what your formulas mean and what context you are using them in. (Ie are you actually doing geometry, or is your AI coding agent just trying arbitrary activation functions for your neuronal net experiments and some of them happen to look like geometry?)
I assume you're saying something other than this though?
[1] https://en.wikipedia.org/wiki/Machine_epsilon
For more, there's a good post on this kind of flag in Rust: https://pythonspeed.com/articles/faster-float-math-rust/
By default, the compiler has to stick to what the standard requires, and can't just say add arbitrary imprecision.
Your epsilon is what you get when you try to analyse floating point numbers as approximations of real numbers. But they also have an independent life as bit patterns, and the compiler can't just willy-nilly muck around with these bit patterns.
Example, this equality check is false:
0.1 + 0.2 == 0.3
Because the last bits of a floating point number, after any practical chain of operations, is practically random, do to errors from limited precision. Yes you can always know what the result will exactly be for any operation, if you know the exact number and operations used. Good luck with something like sin/cos though, where implementations can vary wildly depending on the platform/library.
https://www.netlib.org/fp/dtoa.c is how eg CPython parses literals like 0.3 into floating point numbers. Lo and behold: that algorithm compares floating point number for equality, and would break catastrophically, if the compiler were allowed to willy-nilly fiddle with the bit patterns.
Thanks, I was waiting for this pun the moment turns were introduced in the article.
For example when you do a Taylor series expansion the cos/sin are well approximated by x.
If I were writing the article I would focus on the benefits for derivatives and integration and other things that are slipping my mind at the moment. I wouldn't waste time going down the rabbit hole of why.
At least not for an article aimed at this type of audience.
While not a strict rule, Chesterton’s fence is a good heuristic: before we change something, we should first attempt to understand why it is the way it is.
Hamilton's theory of turns revisited
https://arxiv.org/abs/0904.4787