For general periodic functions, [0, 1) is a good domain. But circles and spheres are geometric objects, and radians/steradians are geometrically significant units that are well suited for general purposes.
I do remember that Doom uses an interesting alternative representation where an angle is a u16 multiple of `(2 * pi) / 65536`. Fixed point is sometimes a good choice in games and simulations due to having uniform precision.
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.
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.
e^(i*x) = cos(x) + i*sin(x)
into something you can kinda understand by staring at the complex plane: -1^(2x) = cost(x) + i*sint(x)
Credit to justinpombrio for this: https://news.ycombinator.com/item?id=32986869If 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.
Let's keep it simple and use just 8 bits. 0° is 0x00, 180° is 0x80, and 255/256ths of 360° is 0xFF. And if we wanted to use signed integers, then 0x80 through 0xFF - the high-bit half of the range - now represent the negative quadrants just as they represent negative integers.
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?
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?
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 and how it converts floating point numbers back to strings. Lo and behold: these algorithm compare floating point numbers for equality, and would break catastrophically, if the compiler were allowed to willy-nilly fiddle with the bit patterns.
The authors of these algorithm did care about floating point equality, and that is not a mistake. (However it would be a mistake to assume that equality of mathematical real numbers translates to equality of floating point numbers.)
> Yes you can always know what the result will exactly be for any operation, if you know the exact number and operations used.
Yes, and for some algorithms like illustrated above this is exactly what people do, and have to do.
And the lower bits of 0.1 + 0.2 ain't random: they are the same on your computer as on mine, whether we run the code in 1999 or in 2029.
https://news.ycombinator.com/item?id=47767398 has a discussion.
[†] Note that this isn't exactly correct since it corresponds to pi = 3.2. A mil is almost the same as a milliradian, but 6400 mils in a circle is much more convenient than 6283.18... milliradians in a circle.
You can calibrate your knuckles by doing this is reverse. Put up a target 1 cm wide and back up until it's just covered by a knuckle. Measure how far you got and divide.
It was when I thought about why this works I started really understanding radians.
Thanks, I was waiting for this pun the moment turns were introduced in the article.
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.
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.
the article acts like radians are arbitrary without discussing this key property.