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.
Perhaps in the physics sense, but in computer science we do have the notion of types which does allow us to model the difference between an angle and other numerics.
Dimensions and units are separate things, though. For example, 1 minute and 1 second are different units of the same time dimension. Similarly, 1 rad and 1 degree are both dimensionless, but they are both different units.
Theoretically, you can define systems of measurement where a lot of seemingly separate things fall on the same units and dimensions. There are "natural units" in physics where you take the fundamental nature of particles and relativity into account and make some convenient choices for some physical constants such as the speed of light c := 1. Then the speed becomes dimensionless, length and time have the same unit and dimension (a length of 1eV is a time period of 1eV), and almost all units are simply derived from a measurement of energy (electron volt, not as basic as people would like, but useful enough).
> Then the speed becomes dimensionless, length and time have the same unit and dimension
Uh, that is not what the article you linked is saying. Natural units don’t make speed dimensionless, nor allow you to use the same unit for length and time. Natural units remove the conversion constants, not the units or dimensions.
It is dimensionless by fiat and convention. It clearly has units such as degrees, grad and radians. Just like other quantities that have units, a specific measurement is expressed as a pure numerical multiple of an unit which may be radians, degrees etc.
This is a known wrinkle in dimensional analysis and people have considered making angles a fundamental quantity such as mass, length and time but have not done so because of the disruption it would cause.
> The current state of affairs leads inevitably to ghostly appearances and disappearances of the radian in the dimensional analysis of physical equations.
In "A spectral unit", Nature Physics (2020) - https://www.nature.com/articles/s41567-020-0997-3.pdf Giacomo Prando summarizes the troubled history of the radian, a unit with the odd property of appearing and disappearing seemingly at will in dimensional formulas
It led me to reading about "dimensionless quantity".
> There have been periodic proposals to "patch" the SI system to reduce confusion regarding physical dimensions. For example, a 2017 op-ed in Nature argued for formalizing the radian as a physical unit.
> The idea was rebutted on the grounds that such a change would raise inconsistencies for both established dimensionless groups, like the Strouhal number, and for mathematically distinct entities that happen to have the same units, like torque (a vector product) versus energy (a scalar product).
What's surprising is that these discussions are so recent, considering the wide implications on so much practical work in mechanics and engineering. Maybe people got so used to working around the question, that any proposed solution would be too disruptive - so it's better to keep things "backward compatible" rather than conceptually clear and explicit.
In another comment someone said, "types" (in programming and type theory, I'd guess) are a poor model of physics units. But I wonder about that, it seems "units" are something like types with associated quantities, like degrees with 360, or meters with the speed of light.
Ensuring units agree is indeed a form of type checking. A more thorough procedure for the former is dimensional analysis.
I think the fact that action and angular momentum have the same units played an illuminating role in making sense in Bohr's model regarding why only certain orbits are allowed.
Not sure how that would play out once angle is considered a fundamental entity.
In another comment I made in this thread https://news.ycombinator.com/item?id=49373317 I think it came to the understanding that a "turn" is similar to a dimensionless quantity, as it takes the full circle/cycle as a fundamental 1. Apparently, using the turn as a unit allows one to get rid of pi and e in Euler's formula in favor of 1 and -1.
You might find the following interesting. It is about trigonometry as practiced by early Indian mathematicians. Rather than using an unit circle they used a circle of 3438 units.
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.
I basically agree, at least for standard functions like sin, cos, tan, exp etc. It is even possible to see mistakes in equations just by checking that all the units to standard functions cancel out making the arguments dimensionless.
On the other hand I am still unhappy with calling the ratio of two quantities, that happen to have the same units, "dimensionless". This way, you could create any two "dimensionless" quantities and try to compare them or use one in place of the other which might be meaningless.
Yeah, "dimensionless" would mean they have equal dimension, which would mean they are comparable, which isn't necessarily the case. E.g. both radians and degrees are called "dimensionless".
This is a great paper from NIST that gets into some of the problems with the limit of ‘dimensionlessness’ in metrology and the SI, and in particular issues like the fact that Hertz is considered a coherent SI unit but radian isn’t.
> one conclusion that is not
optional is that the unit hertz cannot be regarded as a
coherent unit of the SI, in contrast to its designation in the current form of the SI, where cycles are ignored and Hz
may be replaced by s^−1
One thing I found especially interesting:
They argue that you can express the (complex) exponential function exp(x) as a power series with powers x^k. They do not say it explicitly, but if we assume the power series comes from a Taylor series, then the k-th factor 1/(k!) is the derivative evaluated at x=0. And the k-th derivative has exactly the unit needed to cancel the unit of x^k. So, all summands of the series are unitless and hence the exponential function's argument is unitless.
This argument would hold for any function which can be written as a series like this.
I am wondering whether this is actually a "problem" of the derivative operator.
> 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.
I mostly agree with your explanation, but would like to emphasize that this is just a convention from mathematics which mostly carries over into physics and engineering. We like to define functions that are R -> R and similar, instead of defining special sets like R° = { r * 360° | r \in R }, corresponding to "real numbers with unit degrees", and then defining functions like sin: R° -> R. It’s just simpler to define and analyze most functions from R -> R and so we mostly do that.
But if you look up physics papers, it’s not uncommon to define functions that require unitful inputs as well. For example, the wave function in the Schrödinger equation maps a position r (3D vector with unit meter) and time t (scalar with unit seconds), to a probability amplitude (complex number with unit m^-3/2), so that \int |ψ(r,t)|^2 d3r becomes a scalar (a probability). Up wave function is still considered a function by all physicists.
The reason for preferring functions defined over domains like R is that it’s a field, and so I can do things like multiply and divide and add and subtract inside it.
If instead we start defining ‘amounts of distance’ as some set D and ‘amounts of time’ as some set T, I have all sorts of extra work to do to make it so that products of amounts of distance are ‘amounts of area’ and amounts of distance over amounts of time are ‘amounts of speed’.
‘Dimension’ is the mathematical tool that lets us bundle all that up into something that we can deal with separately, alongside a real number. And of course you can totally make functions that are dimensional - but it affects what you can do with your functions, like composition and differentiation.
You can apply functions to anything. That's the only thing "function" means. They transform values into other values, and there is no limit on what kind of values you might want to talk about.
This is precisely why (programming language) types are poor model of physics units, despite often being touted for this exact use case. 3m is not the same thing as "the value 3 of type meter". It is the multiplication of the dimensionless scalar 3 with the special "m" constant for meters.
That's why pow(3m, 2) = 9 m^2, and not `the value 9 of type meter`. Of course, you can define the type `square meter` as well, and define `pow -> meters -> positive integer -> square meters`. However this quickly becomes overwhelming once you start doing more complex expressions with multiple types. What is the type of `pow (3kg^2 * m/s, 3/2)`?
Isn't the "special constant" exactly "value 1, type meters", defined as equal to "value <...very large number...> type atoms" etc?
If not, then what would be the result of the multiplication of 3 with "m"?
> Of course, you can define the type `square meter` as well, and define `pow -> meters -> positive integer -> square meters`
As long as your power is an integer, you can reduce it to multiplication. So what you'd really want to define is the result of "<value1 of type meter> * <value2 of type meter>", "(<value1 of type meter> * <value2 of type meter>) * <value3 of type meter>" etc.
What this gets you in the end is a type algebra, but that is also not exactly a new concept.
> If not, then what would be the result of the multiplication of 3 with "m"?
The answer is not, and the result of 3 multiplied by m is 3m. Just like 3 multiplied by pi is 3pi; or, perhaps more accurately, you can view m as a kind of vector unit, and 3m as the scalar product. Of course, none of this is exactly matching - dimensions are different from irrationals, vectors, complex numbers, etc, they are mostly a thing of their own.
> What this gets you in the end is a type algebra, but that is also not exactly a new concept.
Sure, that's why I said specifically programming language types. I am aware that type theory has way more complex operations on types. I think some of these may even be expressible in Idris or Haskell + some appropriate extension. But in almost all programming languages, even ones like OCaml, SML, plain Haskell, Rust, C++ with template magic, Scala, F# and what have you, there is no way to specify that the result of multiplying two values of type A is of type "A * A", especially not in a way that then allows you specify that the division of a value of type "A * A" by A has type A. So types as exposed in any of the common programming languages are horrible for modelling dimensions as used in even high school physics.
> dimensions are different from irrationals, vectors, complex numbers, etc, they are mostly a thing of their own.
I harbor a terrible internal mental model of dimensions which I have never really validated or explored fully, where I like to think they might be vector exponents, or something vaguely similar. If we assign each dimension to be a dimension of a vector - (length, mass, time, etc…) then a ‘distance’ might be e^((1,0,0,…)); a ‘duration’ e^((0,0,1,…)).
These have the requisite properties that when we multiply and divide them, we end up adding and subtracting these vectors.
So a distance times a distance is e^((2,0,0,…)) and a distance over a duration (a speed) is e^((1,0,-1,…))
They have the right basic algebraic behavior but who knows what terrible consequences they would have.
No, it's definitely possible in mathematics, they've left out some details as to what the units are doing that makes them unable to be assigned to functions. I mean a regular ODE that you get from newtons laws is a set of functions that take position and time as inputs, which all have units. What they mean should be "dimensionless functions cannot be applied to dimensional variables". These are commonly functions like sin cos exp log and so on.
I don't think of it as units (as the sibling comment pointed out, angles are dimensionless); I think of ° as a postfix unary operator that does the conversion. In other words, I read sin(x°) as a shorthand for sin(x*Pi/180).
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.
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.
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.
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.
This statement is a little too strong. It's a mistake to care about the equality of floating point numbers after subjecting them to irrational operations. On the other hand, the entire internet runs on the fact that doubles exactly represent the integers up to 2^53.
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.
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.
It depends on your context, and is mentioned in the article. The advantage of turns comes from the fact that the implementation of sinᵣ etc. is internally doing a conversion to turns, so by using sin_turns directly, you avoid calculating π/π with every call.
It’s not a call for someone doing calculus or solving differential equations to abandon radians, just for the particular case of getting a numerical value for sin, cos, etc. from a library, having direct access to a turns-based function would produce faster code and also avoid some of the rounding errors that come from that π/π not to mention the imprecision of any angle that isn’t 0.
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 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.
I've used Taylor series in numerical optimization. A function we were implementing needed to be differentiable (for automatic differentiation), but its definition had a special case, so we used a couple terms of the Taylor series in the special case.
I have used the Taylor series approximations to produce the LUT over a defined interval. This may be generated pre-complication or at startup with a defined precision depending on the destination signed type.
Tend to use radians because we're moving from written proofs or simulations into embedded code in such systems. The code needs to read and work the same as those.
Our favorite WebAssembly is an example! It specifically excludes trigonometry from the spec, because real hardware doesn't produce exactly the same results.
So mathematical libraries in WASM reimplement the trigonometric functions using series.
Why are math libraries consistently treated as space hogs if you don't keep them as barebones as possible? I've had sinDeg/cosDeg overloads for a while and I don't see why they can't be built into the base library; the same would go for a sinT/cosT that takes turns instead of radians or degrees. Why do we have to pick one and meticulously avoid having multiple?
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.
TFA states “the less tau and pi, the better” and calls the radian-oriented functions “legacy”. I understand that a title like “Turns are Better than Radians” is intentionally inflammatory to get clicks, but I’d expect a more calibrated take in the article body. Phrasing like the above indicates the author doesn’t know what they’re talking about, even though I do agree turn-oriented functions would be useful.
> 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.
Binary fractions of a turn are also a nice intuition pump for two's complement in general.
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.
One weird unit for angles is the mil, defined as 6400 mils in a circle. This unit is very useful for artillery, since 1 meter displacement at a distance of 1 km is 1 mil [†]. Thus, you can see how much you missed by, divide by the distance, and easily determine how much you need to adjust your aim in mils. Another interesting thing about artillery is they traditionally do a binary search to get the distance correct, which they call "bracketing". Link: https://unitedtaskforce.net/training/sop/communication/artil...
[†] 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.
It's also useful for sighting distances when the width or height of something is known. A knuckle on your outstretched arm is roughly 30 mils, so you cover the thing with your hand, count knuckles, multiply by 30, then divide the size by that number to get the distance.
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.
Oh, and I forgot and now it's too late to edit my comment. 6400 has a bunch of nice divisors too. A half-turn is 3200 mils, a quarter is 1600, a quarter of a quarter is 400, etc. A sixth of a turn is nearly 1000 mils. A tenth is obviously 640 mils.
The C standard defines the functions sinpi(), cospi(), etc. that act on half-turns. If you have a modern compiler, all you have to do is to include math.h
I'm confused. How is this simpler? Is there something in (-1)^(2x) that can easily understood by staring at the complex plane? It seems mostly that you've gotten rid of "e", but one of the goals of Euler's formula IMO is to explain what "e^(i …)" means so I'm not sure how this variant is useful.
Sorry but this is pretty bogus. (-1)^x is only well defined when x is an integer. This is generally the case for r^x whenever r isn't a positive real number. For example, when x = 0.5, r has two distinct square roots. Sure, you can choose one of them arbitrarily and declare it to be the value of r^0.5 (and math libraries typically do this), but there's unfortunately no good way to make this arbitrary choice consistently for all values of r simultaneously.
Funny how the so-called eldritch terror is another face of what is widely considered one of the most beautiful equations in mathematics, Euler's identity that unites five fundamental constants.
e^(i*pi)+1 = 0
..which is a result of the more general formula.
e^(i*x) = cos(x) + i*sin(x)
Pi is hiding there in the sin and cos functions implicitly, because the unit radian is defined by 2*pi. In comparison, the version you mentioned that takes x in "turns".
-1^(2x) = cost(x) + i*sint(x)
It got rid of pi and e, which already is a win for simplicity. i is still there for the imaginary component, or y in the complex plane. So the need for pi was removed thanks to the "turn", defined by 1 as the whole circle or cycle.
Multiplying -1 to itself every half turn makes it an alternating series of 1 and -1.. Weird, but it is visually clear to understand, without involving e. Though I still don't see where e went. Oh, this comment explains:
> If we rearrange the products in the exponent we get
2πix πi2x ( πi ) 2x
e -> e -> (e )
> Where e^(πi) is -1. That shows there is something to the turns units; we can express the analog of the Euler identity using exponentiation using a base and factor which are integers.
Yeah I get it now, a "turn" acts like a dimensionless unit to the circle/cycle.
How about i^4x? It makes it clearer which direction we are rotating (vs -1 which is a 0.5 turn rotation in either direction) and avoids the garden path confusion that could arise from it not being obvious from the left side of the equation that we are working in the complex plane at all.
I argued this idea to a couple of my classmates when I was a physics undergrad, and they agreed. However, I later changed opinions because of what this does to the derivatives/integrals of your trig functions.
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.
Dumb question: For multiplying for smaller turns such as 1 arc-second (1,296,000 in 1 turn), that would floating point precision issues be a tiny slight issue (22619.4671 arc-seconds in 2pi radians), or is it just a coding convention change?
The floating point expressions needed to represent the math library functions with decent precision and performance becomes significantly more weird and complex with turns.
This seems to be mostly from the perspective of what makes the most sense to use at an API boundary.
Rather than trying to agree on the best meaning the various integers or floats that we're passing around, maybe we should instead build a more complex angle type that doesn't force callers to conform. Like, I can pass minutes or seconds to functions that accept a time type and it just works because they're not being collapsed to numbers. Is there any reason we couldn't do that with angles too?
I think it misses the whole point of Pi. Turns are for angles. Pi is not a measure of angle. It is a number that can be used to find the length of an arc. For example, it gives half-length of an arc, given an angle in Turns. So it deals with lengths, not strictly angles. Turns deal with angles only.
Oh yeah, in the era of ¼ circle trig tables (cos and maybe tan; inverse and arc versions as needed) in ROM or Taylor/Maclaurin approximation (with fast integer division) when FPUs were rare. Such tables and tricks mostly fell by the wayside when the 80486DX, 68040, and N64 (VR4300) arrived and SIMD/MIMD systems followed.
I miss strict, deterministic unsigned addition overflow. In many modern languages, all kinds of verbose hoops are required to get this behavior and there's a chance it will generate terrible machine code.
> I miss strict, deterministic unsigned addition overflow. In many modern languages, all kinds of verbose hoops are required to get this behavior and there's a chance it will generate terrible machine code.
Most modern (post-2000) languages actually handle this perfectly fine. They have both signed and unsigned types, with exact bit widths and fully specified semantics, which generally match what the hardware is natively capable of, at least on modern processors.
It's languages from the 1990s that make this complicated. There must have been something in the water that motivated language designers in that decade to "simplify" the number system. Maybe this was an overcorrection from even older languages, which generally weren't trying to be clever but were trying to be portable, at a time when a lot of the basics hadn't been nailed down yet, like 8-bit bytes and two's complement.
I don't know what you consider to be a "modern" language, but the passage of time may not accord with your definition of "modern". Languages like Go and Rust are as old today as C was when Python came out.
202 comments
[ 0.19 ms ] story [ 22.4 ms ] threadMichael 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.
But that's more for analysis of your code / formulas than when you actually go and compute things.
Dimensionless, sure, but what do you mean here? Radians and degrees are units, are they not?
https://en.wikipedia.org/wiki/Natural_units
Uh, that is not what the article you linked is saying. Natural units don’t make speed dimensionless, nor allow you to use the same unit for length and time. Natural units remove the conversion constants, not the units or dimensions.
This is a known wrinkle in dimensional analysis and people have considered making angles a fundamental quantity such as mass, length and time but have not done so because of the disruption it would cause.
More details here
https://en.wikipedia.org/wiki/Radian#Dimensional_analysis
https://en.wikipedia.org/wiki/Angle#Dimensional_analysis
> The current state of affairs leads inevitably to ghostly appearances and disappearances of the radian in the dimensional analysis of physical equations.
In "A spectral unit", Nature Physics (2020) - https://www.nature.com/articles/s41567-020-0997-3.pdf Giacomo Prando summarizes the troubled history of the radian, a unit with the odd property of appearing and disappearing seemingly at will in dimensional formulas
It led me to reading about "dimensionless quantity".
> There have been periodic proposals to "patch" the SI system to reduce confusion regarding physical dimensions. For example, a 2017 op-ed in Nature argued for formalizing the radian as a physical unit.
SI units need reform to avoid confusion (2017) - https://doi.org/10.1038%2F548135b
> The idea was rebutted on the grounds that such a change would raise inconsistencies for both established dimensionless groups, like the Strouhal number, and for mathematically distinct entities that happen to have the same units, like torque (a vector product) versus energy (a scalar product).
Don't tamper with SI-unit consistency (2017) - https://doi.org/10.1038%2F549160d
---
What's surprising is that these discussions are so recent, considering the wide implications on so much practical work in mechanics and engineering. Maybe people got so used to working around the question, that any proposed solution would be too disruptive - so it's better to keep things "backward compatible" rather than conceptually clear and explicit.
In another comment someone said, "types" (in programming and type theory, I'd guess) are a poor model of physics units. But I wonder about that, it seems "units" are something like types with associated quantities, like degrees with 360, or meters with the speed of light.
I think the fact that action and angular momentum have the same units played an illuminating role in making sense in Bohr's model regarding why only certain orbits are allowed.
Not sure how that would play out once angle is considered a fundamental entity.
This sure is a rabbit hole.
https://news.ycombinator.com/item?id=49371421
I remember things the best (only) when I discover them for myself. Slow progress but high retention.
https://news.ycombinator.com/item?id=45129081
‘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.
On the other hand I am still unhappy with calling the ratio of two quantities, that happen to have the same units, "dimensionless". This way, you could create any two "dimensionless" quantities and try to compare them or use one in place of the other which might be meaningless.
Case in point:
https://trac.ffmpeg.org/ticket/11279
https://trac.ffmpeg.org/ticket/11284
https://www.nist.gov/publications/dimensionless-units-si
A key takeaway:
> one conclusion that is not optional is that the unit hertz cannot be regarded as a coherent unit of the SI, in contrast to its designation in the current form of the SI, where cycles are ignored and Hz may be replaced by s^−1
One thing I found especially interesting: They argue that you can express the (complex) exponential function exp(x) as a power series with powers x^k. They do not say it explicitly, but if we assume the power series comes from a Taylor series, then the k-th factor 1/(k!) is the derivative evaluated at x=0. And the k-th derivative has exactly the unit needed to cancel the unit of x^k. So, all summands of the series are unitless and hence the exponential function's argument is unitless.
This argument would hold for any function which can be written as a series like this. I am wondering whether this is actually a "problem" of the derivative operator.
I mostly agree with your explanation, but would like to emphasize that this is just a convention from mathematics which mostly carries over into physics and engineering. We like to define functions that are R -> R and similar, instead of defining special sets like R° = { r * 360° | r \in R }, corresponding to "real numbers with unit degrees", and then defining functions like sin: R° -> R. It’s just simpler to define and analyze most functions from R -> R and so we mostly do that.
But if you look up physics papers, it’s not uncommon to define functions that require unitful inputs as well. For example, the wave function in the Schrödinger equation maps a position r (3D vector with unit meter) and time t (scalar with unit seconds), to a probability amplitude (complex number with unit m^-3/2), so that \int |ψ(r,t)|^2 d3r becomes a scalar (a probability). Up wave function is still considered a function by all physicists.
If instead we start defining ‘amounts of distance’ as some set D and ‘amounts of time’ as some set T, I have all sorts of extra work to do to make it so that products of amounts of distance are ‘amounts of area’ and amounts of distance over amounts of time are ‘amounts of speed’.
‘Dimension’ is the mathematical tool that lets us bundle all that up into something that we can deal with separately, alongside a real number. And of course you can totally make functions that are dimensional - but it affects what you can do with your functions, like composition and differentiation.
Perhaps not in mathematics, but in programming that's clearly possible. I guess programming is more general than mathematics.
That's why pow(3m, 2) = 9 m^2, and not `the value 9 of type meter`. Of course, you can define the type `square meter` as well, and define `pow -> meters -> positive integer -> square meters`. However this quickly becomes overwhelming once you start doing more complex expressions with multiple types. What is the type of `pow (3kg^2 * m/s, 3/2)`?
Isn't the "special constant" exactly "value 1, type meters", defined as equal to "value <...very large number...> type atoms" etc?
If not, then what would be the result of the multiplication of 3 with "m"?
> Of course, you can define the type `square meter` as well, and define `pow -> meters -> positive integer -> square meters`
As long as your power is an integer, you can reduce it to multiplication. So what you'd really want to define is the result of "<value1 of type meter> * <value2 of type meter>", "(<value1 of type meter> * <value2 of type meter>) * <value3 of type meter>" etc.
What this gets you in the end is a type algebra, but that is also not exactly a new concept.
The answer is not, and the result of 3 multiplied by m is 3m. Just like 3 multiplied by pi is 3pi; or, perhaps more accurately, you can view m as a kind of vector unit, and 3m as the scalar product. Of course, none of this is exactly matching - dimensions are different from irrationals, vectors, complex numbers, etc, they are mostly a thing of their own.
> What this gets you in the end is a type algebra, but that is also not exactly a new concept.
Sure, that's why I said specifically programming language types. I am aware that type theory has way more complex operations on types. I think some of these may even be expressible in Idris or Haskell + some appropriate extension. But in almost all programming languages, even ones like OCaml, SML, plain Haskell, Rust, C++ with template magic, Scala, F# and what have you, there is no way to specify that the result of multiplying two values of type A is of type "A * A", especially not in a way that then allows you specify that the division of a value of type "A * A" by A has type A. So types as exposed in any of the common programming languages are horrible for modelling dimensions as used in even high school physics.
I harbor a terrible internal mental model of dimensions which I have never really validated or explored fully, where I like to think they might be vector exponents, or something vaguely similar. If we assign each dimension to be a dimension of a vector - (length, mass, time, etc…) then a ‘distance’ might be e^((1,0,0,…)); a ‘duration’ e^((0,0,1,…)).
These have the requisite properties that when we multiply and divide them, we end up adding and subtracting these vectors.
So a distance times a distance is e^((2,0,0,…)) and a distance over a duration (a speed) is e^((1,0,-1,…))
They have the right basic algebraic behavior but who knows what terrible consequences they would have.
This means 100 gradians to a right angle, so arbitrary small angles feel more like percentages of a right angle.
[0]: https://en.wikipedia.org/wiki/Gradian
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.
Great idea, I will definitely do this!
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.
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.
Thanks, I was waiting for this pun the moment turns were introduced in the article.
It’s not a call for someone doing calculus or solving differential equations to abandon radians, just for the particular case of getting a numerical value for sin, cos, etc. from a library, having direct access to a turns-based function would produce faster code and also avoid some of the rounding errors that come from that π/π not to mention the imprecision of any angle that isn’t 0.
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.
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.
Tend to use radians because we're moving from written proofs or simulations into embedded code in such systems. The code needs to read and work the same as those.
So mathematical libraries in WASM reimplement the trigonometric functions using series.
Example: https://github.com/WebAssembly/wasi-libc/blob/2e6fb9d8ee0cdf...
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.
Imagine it like someone suggesting (understandably) that you express memory sizes in hex: no push to make everybody stop using decimal numbers!
s/trigonometry/calculus
Hamilton's theory of turns revisited
https://arxiv.org/abs/0904.4787
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.
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.
[†] 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.
(cost x, sint x) is a point on the unit circle x turns counterclockwise from (1,0).
cost x + i sint x is a point in the complex plane x turns counterclockwise from 1.
Now look at integer powers of i, a point in the complex plane 1/4 turn from 1:
i^0 = 1 (0 turns from 1)
i^1 = i (1/4 turn from 1)
i^2 = -1 (2/4 turn from 1)
i^3 = -i (3/4 turn from 1)
and we define complex exponentiation such that, for all real x,
i^x = cost (x/4) + i sint (x/4) (x/4 turn from 1)
Multiplying -1 to itself every half turn makes it an alternating series of 1 and -1.. Weird, but it is visually clear to understand, without involving e. Though I still don't see where e went. Oh, this comment explains:
> If we rearrange the products in the exponent we get
> Where e^(πi) is -1. That shows there is something to the turns units; we can express the analog of the Euler identity using exponentiation using a base and factor which are integers.Yeah I get it now, a "turn" acts like a dimensionless unit to the circle/cycle.
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.
Understanding uniform motion: are radians really necessary? | WildTrig
https://youtu.be/CnQXRdgN_7I?si=EiYY99i6mBOIyczI
Wild Trig: An introduction to Rational Trigonometry
https://youtube.com/playlist?list=PLIljB45xT85CyF_7bKd6y36VA...
Please stick to radians.
https://posithub.org/docs/posit_standard-2.pdf
Rather than trying to agree on the best meaning the various integers or floats that we're passing around, maybe we should instead build a more complex angle type that doesn't force callers to conform. Like, I can pass minutes or seconds to functions that accept a time type and it just works because they're not being collapsed to numbers. Is there any reason we couldn't do that with angles too?
I’ve had a brief moment of hope, forgetting the point was about mathematics.
I miss strict, deterministic unsigned addition overflow. In many modern languages, all kinds of verbose hoops are required to get this behavior and there's a chance it will generate terrible machine code.
Most modern (post-2000) languages actually handle this perfectly fine. They have both signed and unsigned types, with exact bit widths and fully specified semantics, which generally match what the hardware is natively capable of, at least on modern processors.
It's languages from the 1990s that make this complicated. There must have been something in the water that motivated language designers in that decade to "simplify" the number system. Maybe this was an overcorrection from even older languages, which generally weren't trying to be clever but were trying to be portable, at a time when a lot of the basics hadn't been nailed down yet, like 8-bit bytes and two's complement.