The math is definitely not fine with turns, because your Euler formula e^ix = cos x + i sin x no longer holds. We can use a base other than e, namely B = e^2pi which around 535.4916. This doesn't have the nice e properties like d/dx e^x = e^x.
The elegant fact that the base of the natural logarithm, which produces an exponential function that is its own derivative, also shows up as the basis for the above Euler's formula, shows that radians are special: like what binary is to computers.
The natural logarithm being its own derivative is in fact directly linked to the derivative a radians-based sin(x) being cos(x) and so on. Make it any other unit, and you have a mess of conversion factors worse than 2pi.
Imagine complex chained derivatives, double and triple derivative, chain and product rules, all stuffed with trig functions and generating gratuitous piles of cascaded conversion constrants because radians were not used.
In another comment, I asked why people chose to use the symbol τ over just writing turn or "rev(olution)" (defined to be the constant ≈ 6.28318530718) given how unambiguous the latter is as a name for 2π. And why not just write sinrev() or sinturn(), and leave the symbols sin() and rev (defined to be ≈ 6.28318530718) alone?
The naming is irrelevant here. The point is that sin(x) ~ x for small x, whereas sinrev(x) ~ rev * x for small x, which is much uglier. And similar things happen to the derivative of sinrev() vs regular sin() and so on. So switching to preferring to express angles in revs instead actually complicates most formulas, at least in some domans.
You either (i) don't know the Greek alphabet, or (ii) can't read people's short posts. I literally mentioned tau and why it might be a silly name (it clashes with other mathematical uses of the symbol tau).
For graphics rendering Euler equation doesnt matter. Colours are 0.0-1.0 and have no relation to reality, but it works. Same with rotations (if we’re not using Quaternikns)
> For graphics rendering Euler equation doesnt matter.
Huh?? "Euler angles" are one of the most popular representations in computer graphics! The only other good alternative is quaternions, where as you say this also matters!
Yes, but do you really need to scale all your values to make the rotation amount fit into a sin() call, only to have to scale them back again when you're done?
I think what they're getting at is "why are we scaling everything so one full turn is sin(6.28ish) when we can just say sin(1)?"
You could easily try it out by defining a function that replaces sin(), cos(), and tan() with their "turn" equivalents, and seeing how you get on.
Also with radians the differential equation x''''(t)=x(t) has {exp(t), exp(-t), sin(t), cos(t)} as the (real) canonical base for its solution space. And x''(t)=-x(t) gets {sin(t), cos(t)} where they even result from the simplest possible (non-trivial) initial conditions (x(0)=0,x'(0)=1 and x(0)=1,x'(0)=0).
If you look at all the simplest differential equations you can think of, the sin(t)/cos(t) functions in radians are almost inevitable independent from their geometric usage.
I can only imagine what a ridiculous problem it would be to try to re-do, for example, the Vincenty formula for distance between two latitude/longitude points on an oblate spheroid (the earth) if it couldn't use radians.
Further, inverse vincenty is pretty much an essential in anything that needs to find the azimuth between two points on a map. Such as for microwave radio link planning purposes.
I absolutely love how full Wikipedia is of completely useless pages like the Vincenty's Formulae one, where someone has just gone "look this is what it says in my maths textbook" without any explanation.
No discussion of why you'd use this over for example the Haversine function, of course, just a straight out copypasta and a demonstration of how clever someone is at the mathematical notation markup.
Incidentally you'd use this instead of Haversine if you wanted to be really really accurate down to millimetres across a long baseline, as opposed to lots and lots of "it's ten miles that way in a straight line" very quickly and simply.
It would sure be better if it had some concrete explanations and examples why vincenty is preferred. It's also barely any more computational load on modern computers so very little reason not to use it.
Haversine is strongly deprecated in even short distance applications like planning a 35 km point to point licensed band radio microwave link, because you risk having both slightly the wrong distance and the azimuth figure being off by a tenth of a degree.
Vincenty in python form is quite compact. Karney by comparison is something like 1000 lines of code. And the difference is going between like a few mm precision to nanometers.
I've actually implemented Haversine in a SQL query to find what can be summed up as "which of these moving things is closest to this thing right now". It's not the tidiest, and I had to ask someone better at SQL than I am to make it entirely work, but it looks like it is easier than doing Vincenty.
I should try it, right?
Edit: I also wonder what's to be gained by being accurate to nanometres over the surface of a fairly inaccurate planet.
My application was to locate movable things to identify which was nearest to a moorland wildfire, where you need to be accurate to within about 1km at best - you don't need to drop the pin right on it, you'll know where you're going when you see it ;-)
For that application you needn't have bothered. On a sphere arc-length and Euclidean distance are monotonically related, so the minimizer would not have changed.
Writing full articles takes time and effort. But the effort is cumulative, so these stub articles are really just the start. Some of the comment you made here would definitely improve the article. You are always welcome to edit and improve Wikipedia. I mean this literally and sincerely, it is one of the few places on the internet where you might benefit from posting.
it is quite telling that wikipedia has pages upon pages documenting pokemon, but relatively limited context about maths or science, beyond what's in textbooks.
It's not a "stub article" though, it's just a paragraph and then a bunch of stuff plagiarised from a maths textbook.
I already edit quite a bit on Wikipedia. I stay away from the maths bits, because it's a little outside my area of expertise - and because it's just things like "it's a function to calculate distance, and here's ten pages of algebra with no explanation" I can't really improve that on Wikipedia.
Latitude and Longitude? By definition it’s not starting in radians. After that, pi is involved but that doesn’t mean you have to use radians, unless you define “anything that uses pi is radians”. The discussion TFA started was about programming computers optimally. If you want the code to be readable by humans with a math background, or Wikipedia background, sure, use the algorithms as written down. TFA was not targeting that audience. It was targeting folks who care about two pointless multiplies in their (checks notes) game engine.
The radians provide absolute no help for your problem.
There are alternative trigonometric functions with the argument measured in cycles that can be used instead of those with argument measured in radians. All formulae written with sin, cos and atan can be rewritten with sin2pi, cos2pi and atan2pi, or whatever names you want for those functions.
Moreover, before the electronic computers, nobody in the entire history of mankind had used trigonometric functions with arguments measured in radians for any practical problem, like astronomical or geodesy problems.
The radians became popular in the 19th century, only for symbolic computations, because they simplify the formulae for derivatives and primitives.
For all numeric computations, even in the 19th century, nobody used trigonometric functions with arguments measured in radians, but only trigonometric functions with arguments measured in sexagesimal degrees, which behave much more similarly to the functions with arguments measured in cycles, than to the functions with arguments measured in radians, which cannot be computed exactly for any rational argument, and where the argument can never be reduced exactly to a value in the first quadrant.
While the trigonometric functions with arguments in radians are harmful, the constant 2Pi remains an essential constant, which must be used to convert between the length and the central angle that correspond to a circular arc, and also to compute the derivatives and primitives of the exponential 1^x and of the trigonometric functions.
The sin function has Indian and Greek roots. Part of that history is in the name 'sin' itself. I will let you all look that up. It's quite a funny story especially the jya to jayb bit.
This comment is about computation of sin in Indian mathematics and its definition.
The analogue of the sin function in Indian mathematics was a function from length to length. It was defined as the length of the half chord that corresponds to the angle, not of a unit radius circle but of a circle of radius 3438 units.
But why 3438 ?
That requires understanding the Indian system of measuring angles by length.
They wanted to have a numeric precision of 1 arc minute but weren't very fond of manipulating fractions. So they incorporated their requirement in how they standardized their circle -- Not by radius or diameter but by arc length. They chose that circle to be the standard for which the arc length of one arc minute is unit length.
If one does the math, it is 360 * 60 / 2π. Plugin the accuracy of π that was known to Indian mathematicians of that time you get a radius of 3438 units.
If you are curious about their numeric calculation of sin look up Aryabhatta and Bhaskara. Wikipedia is quite informative.
Something akin to radians was widely used in ancient India. That is, sine tables constructed for a circle with circumference 360·60 (angular minutes) and radius 3438 ≈ 360·60/2π.
In Europe, radians per se developed in the early 18th century. What is true is that the name radian came about in the late 19th century.
> trigonometric functions with arguments in radians are harmful
Trigonometric functions are not inherently "harmful", but they are sometimes cumbersome. Changing the units doesn't make all that much practical difference.
Avoiding transcendental functions in favor of vector methods is often a good strategy though, especially in code.
It doesn't really change Euler's formula. It just adds a factor for x to it (or an additional term to hide inside sin and cos as functions). That's less convenient, not less true.
However, I don't really see a benefit gained out of doing this to keep your theta between -1 and 1 instead of between -2pi and 2pi. Like it's not a difficult thing to estimate or convert in your head to get a close enough estimation.
The author's not talking about doing math, but about porting math into code. Counting turns is the same as counting cycles. People do that all the time. It works fine.
And this math is kind of a mess. exp(x) is its own derivative but the log is not. (d/dx)log(x) = 1/x
But, agreed, if you're going to do calculus, use radians.
If you look at the implementation of sqrt for a computer, it's usually implemented with Newton's algorithm, which is an iterative numerical method with high speed convergence. It is computationally efficient and looks approximately zero how √ looks.
Sometimes a person will tell a story which is untrue, with the purpose of bringing levity to a conversation. This may be termed a joke. These stories may also be used to illustrate a point.
It's important to note that such cases are not always clearly signaled as being humor or untrue. It is a part of the joke's effect that the reader or listener will not at first know it is a joke, but will realize it after noticing an absurdity.
I’ve been writing code for 46 years. Not once have I had to code a derivative.
And for all the people who are concerned about how sin' 2πx = 2π cos 2πx, in actual code, it doesn’t matter. Let’s say that I’m writing a basic graphing function and I want to be able to display the slope of the sin curve at any point.
I am not going to expose the turn-based units to the user. Caring about slopes implies that I’m doing calculus and thus assuming radians. So even though my internal values are [0,1], I will label them as [0, 2π] (and the actual numeric values on the display may actually be something like [50,450] which is yet another numeric value we don’t display). So to get the slope at π/4, I’ll calculate cos_t 0.125 and display that value.
We do all kinds of unit translations in computing without worrying about it. This is just another case of that which observes that numerically speaking, using turns is better aligned with the underlying numerical algorithm for calculating trig values.
> I’ve been writing code for 46 years. Not once have I had to code a derivative.
Haha !
I have been coding for much shorter time but having done some ML on orientations and on spheres in my time, I have had to take their derivatives all the time.
It will be interesting to consider folks who do machine learning on robot trajectories or analysing dynamics of robotic arms.
The derivative of log x being 1/x is "clean", free of arbitrary constants. If we change away from e being the base, we lose that.
The derivative of log_b x is 1/(x ln b), where ln b is 1 if b is e.
The computational aspect of it is totally compelling. The library routines are already using turns internally, so it is wasteful to go from/to radians when the caller doesn't require it, and many callers can be rewritten not to. Plus the part argument about common angles like multiples of the right angle having to be irrational numbers under radians is also compelling.
Assume people have read the article and understood it.
The author didn't argue that you should never use radians, or tau. Just that for some use cases there is an alternative that is simpler using turns. Your argument can be true and his proposal can also be true, it just depends what your use case looks like.
That formula as such has no importance at all, it is just a correspondence between different notations.
What you really mean is that there are certain mathematical problems where the complex exponential function is useful and for the complex exponential it is more convenient to measure the real part in nepers and the imaginary part in radians (in order to have a simple formula for computing its derivative and its primitive).
However, the problems where the complex exponential is truly useful are at least an order of magnitude less numerous than it appears from the manner in which mathematics is taught in schools, following a tradition from the 19th century, when symbolic computations done with pen and paper were more important than numeric computations.
For the vast majority of practical problems, the complex exponential is not useful at all (i.e. using it introduces unnecessary complications, without providing any advantage), but a pair of other exponential functions is much more useful, because they ensure computations that are both faster and more accurate: the binary exponential 2^x, with real argument and value, and the exponential 1^x, with argument measured in cycles and a value that is a complex number of unit norm (unit modulus).
Using the pair of exponentials from above, removes computations that are slow and inaccurate (for the reduction of the arguments) from each function evaluation, by moving them to the computation of derivatives or primitives, which are operations that happen much more seldom and which also can frequently be done at compile time, instead of at run time.
Any algorithm that is described by using complex exponentials can be rewritten to use only 2^x and 1^x, and this normally allows various simplifications in the numeric computations. Even the formulae for Fourier transforms are simpler.
The author of the TFA is perfectly right and the use of nepers and radians is a very bad habit, which is a handicap with which most people remain after being taught mathematics in schools, with antiquated methods.
While in TFA the author uses the term "turn" for the unit of plane angle, the traditional name, which was used until some time after WWII, was "cycle", from which various other unit names where derived, e.g. "cycles per meter" or "cycles per second".
As I have already said, and I am an electronics engineer, the design of any electrical or electronic system, including anything that uses AC power, can be done faster and with less numerical errors, if instead of using complex exponentials one uses 2 other exponential functions: "2^x" and "1^x", with arguments and value domains as I have written above.
Unfortunately, this requires the use of a custom library of transcedental functions, because the standard libraries of most programming languages provide only the functions with arguments in nepers and radians.
The standard C library has attempted to add the missing functions, but for a completely impossible to understand reason the standard has defined wrongly the trigonometric functions, requiring arguments measured in half cycles, instead of cycles.
This is an extraordinarily stupid mistake, but at least if a standard C library implementation has all the functions, it is easy to modify the sources of the trigonometric functions with arguments in half cycles, to take arguments in cycles instead.
Why not e^{2 pi i x} = cos x + i sin x then? We already handle e^{2 pi/360 i x} = cos x + i sin x for x in degrees just fine. It's not that euler no longer holds, it's that you just have to be clear about what units[0] you use when comparing the explicitly angular/geometric cos and sin with the numeric exponential, and then deciding on a default numeric cos and sin/a default "unit" for angles.
If we want to get real interesting with it, this could also motivate an explicitly geometric "unit" aware exp operation, and depending on the defaults we use for the angular scale and the linear scale, 2 pi could be the conversion factor, making exp(2 pi i x) = cos x + i sin x actually interesting and useful and clarifying.
[0] pedantically, they're not units, or at least not dimensional units, so whatever the word for dimensionless units are, as in degrees vs radians vs turns.
The problem is that angles in the complex plane are related to multiplication, which is related to exponentiation.
When you multiply two complex numbers z1 and z2, their angles add: Arg(z1 z2) = Arg(z1) + Arg(z2).
That carries into exponentiation: Arg(z^2) = 2 Arg(z). The exponent 2 has an interpretation as doubling the angle.
In other words, e^2πix has an interpretation as working with angles.
When you have that 2π in there, but not in the sin and cos expressions, you're using different angles for multiplication/exponentiation and for sin/cos.
Your left side shows that you are sticking with Arg(z) being in radians!
But on your right side, you have turns: the expression cos x + i sin x is literally saying that the point whose angle is x on the unit circle in the complex plane is the complex number <cos x, sin x>.
But your left side essentially says that the Arg of this point: Arg(cos x + i sin x) is not x, but 2πx!
When we have a point on a unit circle whose Arg is x, then if we raise e to the power of ix, we get that point. That's what the original left hand says, without the pi.
You have a "trigonometric angle" and "Arg" that are separate, right in a fundamental equation.
If we add types or a geometric abstract manifold or something, the issue is that we do want cos and sin to take numbers with a scale (e.g. cos(90 degrees) vs cos pi/2 rads), but we generally don't give the same thing to e or exponentiation (no e^i(pi/2 radians) vs e^i(90 degrees).
> But on your right side, you have turns: the expression cos x + i sin x is literally saying that the point whose angle is x on the unit circle in the complex plane is the complex number <cos x, sin x>.
I totally agree here, and that's purely geometric, regardless of what we express x in. We can talk in terms of abstract points without specific coordinates/embeddings in R.
> When you have that 2π in there, but not in the sin and cos expressions, you're using different angles for multiplication/exponentiation and for sin/cos.
This part I'm not following. When we talk about a scale, any purely universal identity like Arg(z^2) = 2 Arg(z) is going to hold regardless of the scale. I agree that the Arg stuff nicely motivates interpreting it as an angle, but don't see how it says anything at all about the scale in question. Like, we get an interpretation of e^2πix as working in angles from the Arg reasoning, but we don't get a scale for those angles from it, do we? We'd only get Arg if we impose a scale on Arg itself, right?
So if we take e^2πix at x=1/2 turn=1/2, we get e^πi=-1, which gets us Arg(-1)=1/2 turn=pi rads=180 degrees, and we can work from there, but I still don't see how it imposes a unique scale that we can say is still radians and thus incompatible with the RHS's scale of turns.
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.
edit: Sorry, to clarify, this was a function involving trigonometry but not simply vanilla sine or cosine. However, angular values being represented in radians did help in the same way I described in the parent post.
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.
It all began with replacing frequent occurrence of 2π in calls of sin and cos functions with τ.
This post suggests an optimisation by getting rid of τ by getting rid of radians. That way one can get rid of frequent and adjacent radians to degrees conversions and back.
I say, let's get rid of sin and cos itself !
Of course I am being over the top here. However, if you represent angle not as a scalar in degrees, radians or turns but as a tuple (sin, cos), one can usually dramatically reduce the number of calls to trigonometric functions. Rational polynomials and square root suffices. Recall rotation is a linear transformation with a matrix whose entries are in terms of sin and cosine.
As an API it might not be convenient but consider converting angles internally into a tuple of sin and cosine and keep it that way if your code frequently calls trigonometric functions.
(Aside: Sometimes I prefer keeping the tuple in terms of half angles. Tan half theta is nice to have. And I am embarrassed by the number of comments I have made on this post)
If you want a single number (e.g. you are trying to serialize a lot of data), in many contexts you can replace the coordinates (cos θ, sin θ) with the stereographic projection h = tan ½θ = sin θ / (1 + cos θ). Converting back and forth between these representations is cheap and easy: cos θ = (1 − h²) / (1 + h²) and sin θ = 2h / (1 + h²).
Damn :) why did I not think of that. This would be useful for serialization deserialization.
I have used half angles ½θ because there is no ambiguity about the full angle θ if I know it's sin value (and of course this holds for tan ½θ). Tan works better because one does not have to remember to take the correct branch of sqrt(1 - sin^2 θ).
I learned two clever tricks in this discussion: (i) your tan ½θ and (ii) free modular arithmetic by embedding turns in signed integers.
Oh! I did not know you were a contributing author to wikipedia.
That is one fantastic page. It's a pity if it's sitting there as a draft. At the least have it on your blog.
Half angles substitution is of course a common exercise trying out symbolic integration of many trigonometric integrands. That will s where I encountered it most frequently.
The similarity between hyperbolic and trigonometric angle is also one of my favorite things.
What I found interesting is that we think in terms of slightly different but equivalent pictures. Mine is
I think in terms of angle CAD and the angle subtended on the circumference on the opposite side of the center by the arc AB.
Rotations tickle me just right. One thing I had thought of is turtle graphics motion on the sphere over great circles. Turns out it is not an original thought at all.
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.
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).
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 simple/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.
Certainly pi (and e) must be one of those fundamental constants regardless of any unit of measurement. A "turn", on the other hand - well, if we consider 1 as a dimensionless constant that means a "whole"..
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
> 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)`?
Edit to add: also, there is a simple fact that "sin(pi/2 kg)" is just not defined, in programming or math or physics or any other useful system. It's definitely not 1kg, just like sin ( (pi/2) * 2) is not sin (pi/2) * sin (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.
Having read over this entire conversation I feel that people are almost uniformly missing the practical impact of this, which is simply that you can write your own math in terms of "turns" as much as you like. Nothing stops you right now. Defining a sinT function that takes turns is trivial. And so on for all the functions.
I haven't done much graphics programming, but what I did I did with tau rather than pi. You all seem to be arguing about whether or not you need to enter some parallel universe where all the math is completely rewritten or something, but you don't. It was easy. It didn't clash with the universe at all. I just used "tau" instead of "2 * pi". That's, like, it. That's all there is to it. "const TAU = 2 * PI;" and I was done with the conversion work. Similarly, all that is being suggested is that instead of "sin(2 * pi * (1/4))" you define something like sinT and write "sinT(1/4)".
Seriously. That's it. You don't need to rewrite every math library in the world. You don't even need your math library to support it at all, these are not complicated wrappers. You don't need to redo the whole of calculus to worry about taking derivatives of it or whatever. Besides, degrees already has all the same problems and we use them a lot too anyhow. Having trig function variants that take degrees isn't that uncommon, this is just another variant. You don't need to go in to your math library and remove everything that isn't based on turns. You don't need to force it in the face of the user of your code.
It's true that the benefits of this approach are modest but the costs are way, way less than a lot of the posts seem to be arguing about. The costs are a few local function definitions and a new possible unit for the programmer to have to think about. How expensive that is depends on the local programming language and whether or not you can press the type system into service to represent units in a sane way, and even that is not a problem created by this proposal because I'd want radians and degrees isolated in the same way already.
If you are programming in a language or environment that has no (practical) way to encode the units into the type system, and you had a program that settled on "every angle is radians" I don't think I'd introduce this into my code base. But if you have something where you can very easily integrate it with the existing code and get very solid guarantees that my new "turns" unit is compile-time guaranteed to never mix with "radians" or "degrees" I'd definitely consider it.
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.
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.
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.
The nice thing about turns is that they can be represented by an unsigned integer. For example with an 8 bit unsigned integer:
- 0000_0000 = 0 or tau
- 1000_0000 = pi
- 1100_0000 = 3*pi/4
And the addition and multiplication by integer scalars all apply and the overflows work naturally. I wrote a little library in rust [0] to help with this as you can define the operations */+-% etc.
If you're going for "turns", then I would go even further and argue that it shouldn't be represented as a float, but rather a fixed point (signed?) integer. With 0x00000000 being 0°, 0x40000000 90°, etc. You get modular overflow for free, and the precision is consistent all around the circle.
> 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.
Them there is fightin’ words. Also, as pointed out by an illustrious colleague: Euler’s formula doesn’t work, and pretty much all of complex analysis breaks along with it.
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?
The Fortran 2023 Standard introduces new intrinsics:
"The intrinsic functions ACOSPI, ASINPI, ATANPI, ATAN2PI, COSPI, SINPI, and TANPI are trigonometric functions in which angles are specified in halfrevolutions (that is, as multiples of π)."
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?
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 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.
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.
Rather than sin(), cos() and motion on a circle it is fun to consider uniform speed motion along the perimeter of a regular polygon and its projection hor() and ver() along horizontal and vertical directions.
You can parameterized the motion in terms of the time T to complete one period and consider it's horizontal (or vertical) shadow at any t mod T.
This is related to DFT. As one increases the number of vertices of the regular polygon we will recover sin and cos in the limit. 2 \pi will show up in the ratio of the distance covered in one period of the uniform speed motion and the extents of the projected motion.
Another interesting (and fundamental) construction is to forget about circles and polygons entirely. Simply consider a periodic function over a bounded length L. Consider first the discrete case where the domain is divided into k parts. We want to find an orthonormal basis for all nicely behaved (smooth) periodic functions on this domain.
But there are infinitely many orthonormal basis sets for periodic functions on this domain. We are free to choose any. One choice is that adjacent values do not have large adjacent differences. This can be measured by squared adjacent differences. We choose that basis set that minimizes this quantity.
For the discrete case we recover DFT basis and taking limits carefully we end up with sinusoids.
\Pi will show up because of the requirement of orthonormality.
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.
My gut instinct was that operations like sin, cos, tan, etc, were the kind that would get aggressively inlined by any modern compiler, and then after inlining the redundant conversions between radian/turns would be canceled out by optimization passes.
Of course, gut instinct can be wrong, so I checked in godbolt and was surprised to find out that even if I try to force lto, it still doesn't get inlined and remains a call.
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.
Well, \tau vs \pi is a question of taste, but 1 vs. \tau (or \pi) is not. Because you don't get rid of these weird constants, because \pi (or \tau) is, as a fact, in the circumference and area of circles and in surface and volume of spheres, and in other places. There jus is a weird constant.
And for APIs, you could reasonably well have turns or radians or degrees or even percentage of turns, whatever -- it depend on the context what is 'better'. What's really missing, I think, is the support of units in programming languages (in the type system) so that you cannot mess up when invoking sin()/cos(), because you would be forced to provide a unit.
This can be useful for some geometry, but pi isn't a completely arbitrary choice and some useful relationships are lost when not using radians.
I use different angle units depending on the application. On a platform with 8-bit index registers, 1/256 of a turn can be useful. IIRC Pico-8 uses turns.
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.
The problem with this is that when I see pi I know we're talking about an angle; when you use turns it's just some number. Maybe in typed languages it would work better.
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.
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.
You do in fact need the complex exponential to define this correctly because the function a^x for nonintegers x is only unambiguously defined when a is a positive real number. For example, your function could be either e^(pi i x) or e^(-pi i x), which trace the circle in opposite directions as x varies over the reals. (They happen to agree when x is an integer.)
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
Oh yeah, in the era of ¼ circle trig tables (cos and maybe tan; inverse (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'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 seems 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 mean, it's just shifting the value conversion in the other direction, isn't it?
Pi is a naturally-emerging concept: it's the ratio of a circle's circumference to its diameter. It just so happens that a lot of useful stuff we do in math operate on that ratio, not on either on the individual values (at least, not those alone).
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.
Indeed, this is what Pico-8 uses for its trigonometric functions[1] (angles go from 0 to 1, instead of from 0 to 2*Pi). I was surprised by this at first, but then I found it is very convenient and simplifies a bunch of stuff.
I'm not super versed on the subject, but I think there's a case where using radians allows you to do direct multiplication without any conversion when trig isn't even involved, for rotation or transformation matrices? In which case this would fall apart rather completely if that doesn't work anymore and wouldn't be any different than switching to degrees, a convenience fix that requires conversion anyway.
It's similar to why taxicab distance is better for distance measurement on limited hardware where sqrt() costs precious cycles. The reason to use sin() though is because it's a lookup table (where it counts) and not a bit of math, so moving to turns isn't necessarily a win.
Turn is a measurement unit, and measurement units are just numbers. So turn ≈ 6.28318530718. You're welcome.
That should put to bed that whole τ crap. "But the symbol τ is used for other things!" Yeah, yeah, yeah, just write turn. Even better, because it's more international and has more precedent, write rev for revolution.
The math is definitely not fine with turns, because your Euler formula e^ix = cos x + i sin x no longer holds. We can use a base other than e, namely B = e^2pi which around 535.4916. This doesn't have the nice e properties like d/dx e^x = e^x.
The elegant fact that the base of the natural logarithm, which produces an exponential function that is its own derivative, also shows up as the basis for the above Euler's formula, shows that radians are special: like what binary is to computers.
The natural logarithm being its own derivative is in fact directly linked to the derivative a radians-based sin(x) being cos(x) and so on. Make it any other unit, and you have a mess of conversion factors worse than 2pi.
Imagine complex chained derivatives, double and triple derivative, chain and product rules, all stuffed with trig functions and generating gratuitous piles of cascaded conversion constrants because radians were not used.
In another comment, I asked why people chose to use the symbol τ over just writing turn or "rev(olution)" (defined to be the constant ≈ 6.28318530718) given how unambiguous the latter is as a name for 2π. And why not just write sinrev() or sinturn(), and leave the symbols sin() and rev (defined to be ≈ 6.28318530718) alone?
The naming is irrelevant here. The point is that sin(x) ~ x for small x, whereas sinrev(x) ~ rev * x for small x, which is much uglier. And similar things happen to the derivative of sinrev() vs regular sin() and so on. So switching to preferring to express angles in revs instead actually complicates most formulas, at least in some domans.
I think it's Tau[0].
[0] https://en.wikipedia.org/wiki/Tau_(mathematics)
You either (i) don't know the Greek alphabet, or (ii) can't read people's short posts. I literally mentioned tau and why it might be a silly name (it clashes with other mathematical uses of the symbol tau).
First sentence of the Wikipedia link:
> The number τ (spelled as tau)
For graphics rendering Euler equation doesnt matter. Colours are 0.0-1.0 and have no relation to reality, but it works. Same with rotations (if we’re not using Quaternikns)
> For graphics rendering Euler equation doesnt matter.
Huh?? "Euler angles" are one of the most popular representations in computer graphics! The only other good alternative is quaternions, where as you say this also matters!
Yes, but do you really need to scale all your values to make the rotation amount fit into a sin() call, only to have to scale them back again when you're done?
I think what they're getting at is "why are we scaling everything so one full turn is sin(6.28ish) when we can just say sin(1)?"
You could easily try it out by defining a function that replaces sin(), cos(), and tan() with their "turn" equivalents, and seeing how you get on.
Euler angles have nothing to do with e^ix = cos x + i sin x. They are a completely different concept.
Yes and no. The x in e^ix is to SO(2) what Euler angles are to SO(3).
This really only says that the connection between Euler's formula and Euler angles is that they're both angles. I would agree with that.
One represents rotation in 2D space, the other in 3D. So I think it's a bit more than that.
I am very familiar :) using euler angles involves using trig functions, which is what this thread is about
Also with radians the differential equation x''''(t)=x(t) has {exp(t), exp(-t), sin(t), cos(t)} as the (real) canonical base for its solution space. And x''(t)=-x(t) gets {sin(t), cos(t)} where they even result from the simplest possible (non-trivial) initial conditions (x(0)=0,x'(0)=1 and x(0)=1,x'(0)=0).
If you look at all the simplest differential equations you can think of, the sin(t)/cos(t) functions in radians are almost inevitable independent from their geometric usage.
I can only imagine what a ridiculous problem it would be to try to re-do, for example, the Vincenty formula for distance between two latitude/longitude points on an oblate spheroid (the earth) if it couldn't use radians.
https://en.wikipedia.org/wiki/Vincenty%27s_formulae
https://www.johndcook.com/blog/2018/11/24/spheroid-distance/
Further, inverse vincenty is pretty much an essential in anything that needs to find the azimuth between two points on a map. Such as for microwave radio link planning purposes.
Karney (2013) is also radian dependent.
https://github.com/pbrod/karney
I absolutely love how full Wikipedia is of completely useless pages like the Vincenty's Formulae one, where someone has just gone "look this is what it says in my maths textbook" without any explanation.
No discussion of why you'd use this over for example the Haversine function, of course, just a straight out copypasta and a demonstration of how clever someone is at the mathematical notation markup.
Incidentally you'd use this instead of Haversine if you wanted to be really really accurate down to millimetres across a long baseline, as opposed to lots and lots of "it's ten miles that way in a straight line" very quickly and simply.
It would sure be better if it had some concrete explanations and examples why vincenty is preferred. It's also barely any more computational load on modern computers so very little reason not to use it.
Haversine is strongly deprecated in even short distance applications like planning a 35 km point to point licensed band radio microwave link, because you risk having both slightly the wrong distance and the azimuth figure being off by a tenth of a degree.
Vincenty in python form is quite compact. Karney by comparison is something like 1000 lines of code. And the difference is going between like a few mm precision to nanometers.
I've actually implemented Haversine in a SQL query to find what can be summed up as "which of these moving things is closest to this thing right now". It's not the tidiest, and I had to ask someone better at SQL than I am to make it entirely work, but it looks like it is easier than doing Vincenty.
I should try it, right?
Edit: I also wonder what's to be gained by being accurate to nanometres over the surface of a fairly inaccurate planet.
My application was to locate movable things to identify which was nearest to a moorland wildfire, where you need to be accurate to within about 1km at best - you don't need to drop the pin right on it, you'll know where you're going when you see it ;-)
For that application you needn't have bothered. On a sphere arc-length and Euclidean distance are monotonically related, so the minimizer would not have changed.
Writing full articles takes time and effort. But the effort is cumulative, so these stub articles are really just the start. Some of the comment you made here would definitely improve the article. You are always welcome to edit and improve Wikipedia. I mean this literally and sincerely, it is one of the few places on the internet where you might benefit from posting.
it is quite telling that wikipedia has pages upon pages documenting pokemon, but relatively limited context about maths or science, beyond what's in textbooks.
It's not a "stub article" though, it's just a paragraph and then a bunch of stuff plagiarised from a maths textbook.
I already edit quite a bit on Wikipedia. I stay away from the maths bits, because it's a little outside my area of expertise - and because it's just things like "it's a function to calculate distance, and here's ten pages of algebra with no explanation" I can't really improve that on Wikipedia.
You might enjoy the much longer and more detailed article https://en.wikipedia.org/wiki/Geodesics_on_an_ellipsoid which discusses the context.
I've read that, quite some time ago, which is how I understand how the Haversine function works. Kind of. A bit. Enough to make it work, anyway.
Latitude and Longitude? By definition it’s not starting in radians. After that, pi is involved but that doesn’t mean you have to use radians, unless you define “anything that uses pi is radians”. The discussion TFA started was about programming computers optimally. If you want the code to be readable by humans with a math background, or Wikipedia background, sure, use the algorithms as written down. TFA was not targeting that audience. It was targeting folks who care about two pointless multiplies in their (checks notes) game engine.
The radians provide absolute no help for your problem.
There are alternative trigonometric functions with the argument measured in cycles that can be used instead of those with argument measured in radians. All formulae written with sin, cos and atan can be rewritten with sin2pi, cos2pi and atan2pi, or whatever names you want for those functions.
Moreover, before the electronic computers, nobody in the entire history of mankind had used trigonometric functions with arguments measured in radians for any practical problem, like astronomical or geodesy problems.
The radians became popular in the 19th century, only for symbolic computations, because they simplify the formulae for derivatives and primitives.
For all numeric computations, even in the 19th century, nobody used trigonometric functions with arguments measured in radians, but only trigonometric functions with arguments measured in sexagesimal degrees, which behave much more similarly to the functions with arguments measured in cycles, than to the functions with arguments measured in radians, which cannot be computed exactly for any rational argument, and where the argument can never be reduced exactly to a value in the first quadrant.
While the trigonometric functions with arguments in radians are harmful, the constant 2Pi remains an essential constant, which must be used to convert between the length and the central angle that correspond to a circular arc, and also to compute the derivatives and primitives of the exponential 1^x and of the trigonometric functions.
Some anecdotes to support and color your point.
The sin function has Indian and Greek roots. Part of that history is in the name 'sin' itself. I will let you all look that up. It's quite a funny story especially the jya to jayb bit.
This comment is about computation of sin in Indian mathematics and its definition.
The analogue of the sin function in Indian mathematics was a function from length to length. It was defined as the length of the half chord that corresponds to the angle, not of a unit radius circle but of a circle of radius 3438 units.
But why 3438 ?
That requires understanding the Indian system of measuring angles by length.
They wanted to have a numeric precision of 1 arc minute but weren't very fond of manipulating fractions. So they incorporated their requirement in how they standardized their circle -- Not by radius or diameter but by arc length. They chose that circle to be the standard for which the arc length of one arc minute is unit length.
If one does the math, it is 360 * 60 / 2π. Plugin the accuracy of π that was known to Indian mathematicians of that time you get a radius of 3438 units.
If you are curious about their numeric calculation of sin look up Aryabhatta and Bhaskara. Wikipedia is quite informative.
https://en.wikipedia.org/wiki/%C4%80ryabha%E1%B9%ADa's_sine_...
https://en.wikipedia.org/wiki/Bh%C4%81skara_I%27s_sine_appro...
> The radians became popular in the 19th century
Something akin to radians was widely used in ancient India. That is, sine tables constructed for a circle with circumference 360·60 (angular minutes) and radius 3438 ≈ 360·60/2π.
In Europe, radians per se developed in the early 18th century. What is true is that the name radian came about in the late 19th century.
> trigonometric functions with arguments in radians are harmful
Trigonometric functions are not inherently "harmful", but they are sometimes cumbersome. Changing the units doesn't make all that much practical difference.
Avoiding transcendental functions in favor of vector methods is often a good strategy though, especially in code.
It doesn't really change Euler's formula. It just adds a factor for x to it (or an additional term to hide inside sin and cos as functions). That's less convenient, not less true.
However, I don't really see a benefit gained out of doing this to keep your theta between -1 and 1 instead of between -2pi and 2pi. Like it's not a difficult thing to estimate or convert in your head to get a close enough estimation.
The author's not talking about doing math, but about porting math into code. Counting turns is the same as counting cycles. People do that all the time. It works fine.
And this math is kind of a mess. exp(x) is its own derivative but the log is not. (d/dx)log(x) = 1/x
But, agreed, if you're going to do calculus, use radians.
> The author's not talking about doing math, but about porting math into code.
If your code doesn't look like the math it's "ported" from, the odds of it being bad code go up like 100x
I tried to make my code exactly match the math it came from, but I didn’t have enough memory to store sqrt(2)
If you look at the implementation of sqrt for a computer, it's usually implemented with Newton's algorithm, which is an iterative numerical method with high speed convergence. It is computationally efficient and looks approximately zero how √ looks.
Right. I was hoping to highlight that difference with a joke.
Sometimes a person will tell a story which is untrue, with the purpose of bringing levity to a conversation. This may be termed a joke. These stories may also be used to illustrate a point.
It's important to note that such cases are not always clearly signaled as being humor or untrue. It is a part of the joke's effect that the reader or listener will not at first know it is a joke, but will realize it after noticing an absurdity.
A related concept is "dry humor".
It is important that they not be clearly signaled.
What? "sqrt(2)" is literally 7 bytes. :)
I’ve been writing code for 46 years. Not once have I had to code a derivative.
And for all the people who are concerned about how sin' 2πx = 2π cos 2πx, in actual code, it doesn’t matter. Let’s say that I’m writing a basic graphing function and I want to be able to display the slope of the sin curve at any point.
I am not going to expose the turn-based units to the user. Caring about slopes implies that I’m doing calculus and thus assuming radians. So even though my internal values are [0,1], I will label them as [0, 2π] (and the actual numeric values on the display may actually be something like [50,450] which is yet another numeric value we don’t display). So to get the slope at π/4, I’ll calculate cos_t 0.125 and display that value.
We do all kinds of unit translations in computing without worrying about it. This is just another case of that which observes that numerically speaking, using turns is better aligned with the underlying numerical algorithm for calculating trig values.
> I’ve been writing code for 46 years. Not once have I had to code a derivative.
Haha !
I have been coding for much shorter time but having done some ML on orientations and on spheres in my time, I have had to take their derivatives all the time.
It will be interesting to consider folks who do machine learning on robot trajectories or analysing dynamics of robotic arms.
> Caring about slopes implies that I’m doing calculus
You could be using the results of calculus, which became frazzled with gratuitous constants because of poor angle units before anyone wrote any code.
You want to keep all the math in radians until you code the calculations; then figure out how to optimize it with turns where possible.
> I’ve been writing code for 46 years. Not once have I had to code a derivative.
It sounds like discussions about "porting from math" do not pertain to you then?
The derivative of log x being 1/x is "clean", free of arbitrary constants. If we change away from e being the base, we lose that.
The derivative of log_b x is 1/(x ln b), where ln b is 1 if b is e.
The computational aspect of it is totally compelling. The library routines are already using turns internally, so it is wasteful to go from/to radians when the caller doesn't require it, and many callers can be rewritten not to. Plus the part argument about common angles like multiples of the right angle having to be irrational numbers under radians is also compelling.
Assume people have read the article and understood it.
> The natural logarithm being its own derivative
the derivative of ln(x) is 1/x
> the derivative a radians-based sin(x) being cos(x) and so on. Make it any other unit, and you have a mess of conversion factors worse than 2pi.
the derivative (with respect to x) of sin(x) is cos(x), regardless of units for x. Otherwise the chain rule wouldn't work
> the derivative (with respect to x) of sin(x) is cos(x), regardless of units for x.
Not if you use "turn"-trigonometric functions, as the author suggests.
turn-sin `t sin(x) = sin(2pi * x)` has `d/dx tsin(x) = 2pi * tcos(x)`.
Your argument is correct and I'm sure you're really smart and all that.
However,
Proportion of code where radians are used to represent rotation in 2D (i.e. turns): 99.9999%
Proportion of code where radians are used to perform higher degree derivatives, symbolic computation, etc: 00.0001%
The author didn't argue that you should never use radians, or tau. Just that for some use cases there is an alternative that is simpler using turns. Your argument can be true and his proposal can also be true, it just depends what your use case looks like.
That formula as such has no importance at all, it is just a correspondence between different notations.
What you really mean is that there are certain mathematical problems where the complex exponential function is useful and for the complex exponential it is more convenient to measure the real part in nepers and the imaginary part in radians (in order to have a simple formula for computing its derivative and its primitive).
However, the problems where the complex exponential is truly useful are at least an order of magnitude less numerous than it appears from the manner in which mathematics is taught in schools, following a tradition from the 19th century, when symbolic computations done with pen and paper were more important than numeric computations.
For the vast majority of practical problems, the complex exponential is not useful at all (i.e. using it introduces unnecessary complications, without providing any advantage), but a pair of other exponential functions is much more useful, because they ensure computations that are both faster and more accurate: the binary exponential 2^x, with real argument and value, and the exponential 1^x, with argument measured in cycles and a value that is a complex number of unit norm (unit modulus).
Using the pair of exponentials from above, removes computations that are slow and inaccurate (for the reduction of the arguments) from each function evaluation, by moving them to the computation of derivatives or primitives, which are operations that happen much more seldom and which also can frequently be done at compile time, instead of at run time.
Any algorithm that is described by using complex exponentials can be rewritten to use only 2^x and 1^x, and this normally allows various simplifications in the numeric computations. Even the formulae for Fourier transforms are simpler.
The author of the TFA is perfectly right and the use of nepers and radians is a very bad habit, which is a handicap with which most people remain after being taught mathematics in schools, with antiquated methods.
While in TFA the author uses the term "turn" for the unit of plane angle, the traditional name, which was used until some time after WWII, was "cycle", from which various other unit names where derived, e.g. "cycles per meter" or "cycles per second".
It’s good to know you don’t want your house powered by AC power anymore. It’s a weird take, but you do you.
As I have already said, and I am an electronics engineer, the design of any electrical or electronic system, including anything that uses AC power, can be done faster and with less numerical errors, if instead of using complex exponentials one uses 2 other exponential functions: "2^x" and "1^x", with arguments and value domains as I have written above.
Unfortunately, this requires the use of a custom library of transcedental functions, because the standard libraries of most programming languages provide only the functions with arguments in nepers and radians.
The standard C library has attempted to add the missing functions, but for a completely impossible to understand reason the standard has defined wrongly the trigonometric functions, requiring arguments measured in half cycles, instead of cycles.
This is an extraordinarily stupid mistake, but at least if a standard C library implementation has all the functions, it is easy to modify the sources of the trigonometric functions with arguments in half cycles, to take arguments in cycles instead.
A similar thought (about 1^x) had occurred to me, but I wasn't aware that it was common practice (in some field, at least).
Do you have a reference?
Why not e^{2 pi i x} = cos x + i sin x then? We already handle e^{2 pi/360 i x} = cos x + i sin x for x in degrees just fine. It's not that euler no longer holds, it's that you just have to be clear about what units[0] you use when comparing the explicitly angular/geometric cos and sin with the numeric exponential, and then deciding on a default numeric cos and sin/a default "unit" for angles.
If we want to get real interesting with it, this could also motivate an explicitly geometric "unit" aware exp operation, and depending on the defaults we use for the angular scale and the linear scale, 2 pi could be the conversion factor, making exp(2 pi i x) = cos x + i sin x actually interesting and useful and clarifying.
[0] pedantically, they're not units, or at least not dimensional units, so whatever the word for dimensionless units are, as in degrees vs radians vs turns.
The problem is that angles in the complex plane are related to multiplication, which is related to exponentiation.
When you multiply two complex numbers z1 and z2, their angles add: Arg(z1 z2) = Arg(z1) + Arg(z2).
That carries into exponentiation: Arg(z^2) = 2 Arg(z). The exponent 2 has an interpretation as doubling the angle.
In other words, e^2πix has an interpretation as working with angles.
When you have that 2π in there, but not in the sin and cos expressions, you're using different angles for multiplication/exponentiation and for sin/cos.
Your left side shows that you are sticking with Arg(z) being in radians!
But on your right side, you have turns: the expression cos x + i sin x is literally saying that the point whose angle is x on the unit circle in the complex plane is the complex number <cos x, sin x>.
But your left side essentially says that the Arg of this point: Arg(cos x + i sin x) is not x, but 2πx!
When we have a point on a unit circle whose Arg is x, then if we raise e to the power of ix, we get that point. That's what the original left hand says, without the pi.
You have a "trigonometric angle" and "Arg" that are separate, right in a fundamental equation.
If we add types or a geometric abstract manifold or something, the issue is that we do want cos and sin to take numbers with a scale (e.g. cos(90 degrees) vs cos pi/2 rads), but we generally don't give the same thing to e or exponentiation (no e^i(pi/2 radians) vs e^i(90 degrees).
> But on your right side, you have turns: the expression cos x + i sin x is literally saying that the point whose angle is x on the unit circle in the complex plane is the complex number <cos x, sin x>.
I totally agree here, and that's purely geometric, regardless of what we express x in. We can talk in terms of abstract points without specific coordinates/embeddings in R.
> When you have that 2π in there, but not in the sin and cos expressions, you're using different angles for multiplication/exponentiation and for sin/cos.
This part I'm not following. When we talk about a scale, any purely universal identity like Arg(z^2) = 2 Arg(z) is going to hold regardless of the scale. I agree that the Arg stuff nicely motivates interpreting it as an angle, but don't see how it says anything at all about the scale in question. Like, we get an interpretation of e^2πix as working in angles from the Arg reasoning, but we don't get a scale for those angles from it, do we? We'd only get Arg if we impose a scale on Arg itself, right?
So if we take e^2πix at x=1/2 turn=1/2, we get e^πi=-1, which gets us Arg(-1)=1/2 turn=pi rads=180 degrees, and we can work from there, but I still don't see how it imposes a unique scale that we can say is still radians and thus incompatible with the RHS's scale of turns.
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.:
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.
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).
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.
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.
edit: Sorry, to clarify, this was a function involving trigonometry but not simply vanilla sine or cosine. However, angular values being represented in radians did help in the same way I described in the parent post.
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.
Example: https://github.com/WebAssembly/wasi-libc/blob/2e6fb9d8ee0cdf...
The time where "turns" are really great is when a whole lot of what you're doing is a phase accumulator.
Let's do a full circle.
It all began with replacing frequent occurrence of 2π in calls of sin and cos functions with τ.
This post suggests an optimisation by getting rid of τ by getting rid of radians. That way one can get rid of frequent and adjacent radians to degrees conversions and back.
I say, let's get rid of sin and cos itself !
Of course I am being over the top here. However, if you represent angle not as a scalar in degrees, radians or turns but as a tuple (sin, cos), one can usually dramatically reduce the number of calls to trigonometric functions. Rational polynomials and square root suffices. Recall rotation is a linear transformation with a matrix whose entries are in terms of sin and cosine.
As an API it might not be convenient but consider converting angles internally into a tuple of sin and cosine and keep it that way if your code frequently calls trigonometric functions.
(Aside: Sometimes I prefer keeping the tuple in terms of half angles. Tan half theta is nice to have. And I am embarrassed by the number of comments I have made on this post)
HN has clumsy filtering, but you're allowed to write π and τ.
Thanks for the push. I was being lazy on my mobile phone.
Note to readers who maybe confused by the parent comment. I was using \pi and \tau.
I just noticed now that my default mobile keyboard has π.
If you want a single number (e.g. you are trying to serialize a lot of data), in many contexts you can replace the coordinates (cos θ, sin θ) with the stereographic projection h = tan ½θ = sin θ / (1 + cos θ). Converting back and forth between these representations is cheap and easy: cos θ = (1 − h²) / (1 + h²) and sin θ = 2h / (1 + h²).
Damn :) why did I not think of that. This would be useful for serialization deserialization.
I have used half angles ½θ because there is no ambiguity about the full angle θ if I know it's sin value (and of course this holds for tan ½θ). Tan works better because one does not have to remember to take the correct branch of sqrt(1 - sin^2 θ).
I learned two clever tricks in this discussion: (i) your tan ½θ and (ii) free modular arithmetic by embedding turns in signed integers.
For more: https://en.wikipedia.org/wiki/User:Jacobolus/HalfTan
Oh! I did not know you were a contributing author to wikipedia.
That is one fantastic page. It's a pity if it's sitting there as a draft. At the least have it on your blog.
Half angles substitution is of course a common exercise trying out symbolic integration of many trigonometric integrands. That will s where I encountered it most frequently.
The similarity between hyperbolic and trigonometric angle is also one of my favorite things.
What I found interesting is that we think in terms of slightly different but equivalent pictures. Mine is
https://upload.wikimedia.org/wikipedia/commons/1/18/Versin.p...
I think in terms of angle CAD and the angle subtended on the circumference on the opposite side of the center by the arc AB.
Rotations tickle me just right. One thing I had thought of is turtle graphics motion on the sphere over great circles. Turns out it is not an original thought at all.
https://news.ycombinator.com/item?id=48732233
That will introduce an interesting new bit-bending avenue since almost all tuples of floats are not valid angle representations in that form.
Good point.
If you also incorporate scale then it is, otherwise they need to be unit normalised.
The unnormalized case is essentially a complex number.
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.
Agreed. Though sometimes it's useful to keep track of 'fake' units like for angles, to make something like dimensional analysis work for you.
But that's more for analysis of your code / formulas than when you actually go and compute things.
> all angles are without a unit.
Dimensionless, sure, but what do you mean here? Radians and degrees are units, are they not?
In a very awkward way: rad is m/m, which is 1...
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.
It is only equal to 1 by convention. If we instead considered the ratio of the diameter to the arc-length then rad would be 1/2.
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).
https://en.wikipedia.org/wiki/Natural_units
That’s the awkward argument for being dimensionless. But we know we have units of angle because we have scale factors to convert between them.
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.
More details here
https://en.wikipedia.org/wiki/Radian#Dimensional_analysis
https://en.wikipedia.org/wiki/Angle#Dimensional_analysis
That's my rabbit hole of the week.
> 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 simple/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.
This line of inquiry also led me to "dimensionless physical constants". https://en.wikipedia.org/wiki/Dimensionless_physical_constan...
Certainly pi (and e) must be one of those fundamental constants regardless of any unit of measurement. A "turn", on the other hand - well, if we consider 1 as a dimensionless constant that means a "whole"..
How Many Fundamental Constants Are There? (2011) John Baez https://math.ucr.edu/home/baez/constants.html
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.
This sure is a rabbit hole.
Thanks for your submission
https://news.ycombinator.com/item?id=49372847
hope it gets picked up.
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.
Yeah. @ttoinou too, I think, had the same thing in mind.
https://news.ycombinator.com/item?id=49371421
I see, maybe it's common sense but I do like "rediscovering" basic facts for myself. (:
Absolutely !
I remember things the best (only) when I discover them for myself. Slow progress but high retention.
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.
https://news.ycombinator.com/item?id=45129081
Now it is customary to standardized on the radius. Early Indian astronomers and mathematicians standardize on the arc length of a minute.
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.
Well you can also square root etc.
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".
Edit: Apparently "same dimension" doesn't imply "same unit".
> 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
You can also create meaningless dimensionless quantities by blindly mashing the number keys on your keyboard. Should we stop using keyboards?
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.
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
> 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.
> You generally can’t apply functions to dimensional units.
Perhaps not in mathematics, but in programming that's clearly possible. I guess programming is more general than mathematics.
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)`?
Edit to add: also, there is a simple fact that "sin(pi/2 kg)" is just not defined, in programming or math or physics or any other useful system. It's definitely not 1kg, just like sin ( (pi/2) * 2) is not sin (pi/2) * sin (2).
> with the special "m" constant for meters.
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.
Having read over this entire conversation I feel that people are almost uniformly missing the practical impact of this, which is simply that you can write your own math in terms of "turns" as much as you like. Nothing stops you right now. Defining a sinT function that takes turns is trivial. And so on for all the functions.
I haven't done much graphics programming, but what I did I did with tau rather than pi. You all seem to be arguing about whether or not you need to enter some parallel universe where all the math is completely rewritten or something, but you don't. It was easy. It didn't clash with the universe at all. I just used "tau" instead of "2 * pi". That's, like, it. That's all there is to it. "const TAU = 2 * PI;" and I was done with the conversion work. Similarly, all that is being suggested is that instead of "sin(2 * pi * (1/4))" you define something like sinT and write "sinT(1/4)".
Seriously. That's it. You don't need to rewrite every math library in the world. You don't even need your math library to support it at all, these are not complicated wrappers. You don't need to redo the whole of calculus to worry about taking derivatives of it or whatever. Besides, degrees already has all the same problems and we use them a lot too anyhow. Having trig function variants that take degrees isn't that uncommon, this is just another variant. You don't need to go in to your math library and remove everything that isn't based on turns. You don't need to force it in the face of the user of your code.
It's true that the benefits of this approach are modest but the costs are way, way less than a lot of the posts seem to be arguing about. The costs are a few local function definitions and a new possible unit for the programmer to have to think about. How expensive that is depends on the local programming language and whether or not you can press the type system into service to represent units in a sane way, and even that is not a problem created by this proposal because I'd want radians and degrees isolated in the same way already.
If you are programming in a language or environment that has no (practical) way to encode the units into the type system, and you had a program that settled on "every angle is radians" I don't think I'd introduce this into my code base. But if you have something where you can very easily integrate it with the existing code and get very solid guarantees that my new "turns" unit is compile-time guaranteed to never mix with "radians" or "degrees" I'd definitely consider it.
One would reap the most benefit if libraries were compiled late for the compiler to optimize away adjacent conversions and back.
With C++ template libraries one can do that but compile times can become a hell.
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.
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.
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.
> Next time you are measuring traffic to your website consider using the appropriate SI unit for measuring requests per second: the Becquerel.
Great idea, I will definitely do this!
Functions are free. Create new ones. Sin1 instead of Sin, Cos1 instead of Cos.
The nice thing about turns is that they can be represented by an unsigned integer. For example with an 8 bit unsigned integer:
- 0000_0000 = 0 or tau
- 1000_0000 = pi
- 1100_0000 = 3*pi/4
And the addition and multiplication by integer scalars all apply and the overflows work naturally. I wrote a little library in rust [0] to help with this as you can define the operations */+-% etc.
[0] https://docs.rs/turns/latest/turns/
Ooh! that overflow is so clever. I would have been proud to have thought of that. Perfect fit for modular arithmetic.
If you're going for "turns", then I would go even further and argue that it shouldn't be represented as a float, but rather a fixed point (signed?) integer. With 0x00000000 being 0°, 0x40000000 90°, etc. You get modular overflow for free, and the precision is consistent all around the circle.
There are a couple of comments buried in this discussion about this. It is really cute and clever.
Although new to me this seems to be an old trick. The unit has a name -- BRAD.
> 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.
“The math is easy!” …proceeds to provide no examples of implementation.
This is very interesting to me, but it would help your argument if you provided how the original Gogot example would be rewritten.
Them there is fightin’ words. Also, as pointed out by an illustrious colleague: Euler’s formula doesn’t work, and pretty much all of complex analysis breaks along with it.
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?
The Fortran 2023 Standard introduces new intrinsics:
"The intrinsic functions ACOSPI, ASINPI, ATANPI, ATAN2PI, COSPI, SINPI, and TANPI are trigonometric functions in which angles are specified in halfrevolutions (that is, as multiples of π)."
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?
[1] https://en.wikipedia.org/wiki/Turn_(angle)
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?)
It's a mistake to care about equality of floating point numbers [1]. You must usually consider the lower bits of the number as random.
I assume you're saying something other than this though?
[1] https://en.wikipedia.org/wiki/Machine_epsilon
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.
For more, there's a good post on this kind of flag in Rust: https://pythonspeed.com/articles/faster-float-math-rust/
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 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.
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.
Rather than sin(), cos() and motion on a circle it is fun to consider uniform speed motion along the perimeter of a regular polygon and its projection hor() and ver() along horizontal and vertical directions.
You can parameterized the motion in terms of the time T to complete one period and consider it's horizontal (or vertical) shadow at any t mod T.
This is related to DFT. As one increases the number of vertices of the regular polygon we will recover sin and cos in the limit. 2 \pi will show up in the ratio of the distance covered in one period of the uniform speed motion and the extents of the projected motion.
Another interesting (and fundamental) construction is to forget about circles and polygons entirely. Simply consider a periodic function over a bounded length L. Consider first the discrete case where the domain is divided into k parts. We want to find an orthonormal basis for all nicely behaved (smooth) periodic functions on this domain.
But there are infinitely many orthonormal basis sets for periodic functions on this domain. We are free to choose any. One choice is that adjacent values do not have large adjacent differences. This can be measured by squared adjacent differences. We choose that basis set that minimizes this quantity.
For the discrete case we recover DFT basis and taking limits carefully we end up with sinusoids.
\Pi will show up because of the requirement of orthonormality.
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.
and that's exactly what we did in the old days of 8 bit games. We called them BRADs but others had their own names.
My gut instinct was that operations like sin, cos, tan, etc, were the kind that would get aggressively inlined by any modern compiler, and then after inlining the redundant conversions between radian/turns would be canceled out by optimization passes.
Of course, gut instinct can be wrong, so I checked in godbolt and was surprised to find out that even if I try to force lto, it still doesn't get inlined and remains a call.
I don't think compilers are smart enough to realize that multiplication with tau, followed by multiplication of 2/pi should be simplified away.
Also, sin is probably used so much that inlinung would probably inflate binary size significantly.
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.
Well, \tau vs \pi is a question of taste, but 1 vs. \tau (or \pi) is not. Because you don't get rid of these weird constants, because \pi (or \tau) is, as a fact, in the circumference and area of circles and in surface and volume of spheres, and in other places. There jus is a weird constant.
And for APIs, you could reasonably well have turns or radians or degrees or even percentage of turns, whatever -- it depend on the context what is 'better'. What's really missing, I think, is the support of units in programming languages (in the type system) so that you cannot mess up when invoking sin()/cos(), because you would be forced to provide a unit.
> It turns out (pun intended!)
Thanks, I was waiting for this pun the moment turns were introduced in the article.
Here's an even better idea: instead of turns, use degrees!
Or you could use 1/360 of a turn.
degrees were primarily chosen due to many integer divisors - likely for applications of time and seasons.
I always liked gradians [0]. 400 gradians to a turn.
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
This alone should be a reason to drop the pi factor: it's basically impossible to get an exact zero for the sine of a half-turn:
sin(1*pi) = 1.2246e-16
This can be useful for some geometry, but pi isn't a completely arbitrary choice and some useful relationships are lost when not using radians.
I use different angle units depending on the application. On a platform with 8-bit index registers, 1/256 of a turn can be useful. IIRC Pico-8 uses turns.
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.
You might have misunderstood TFA. No push for trig reform, just a consideration on what internal representation is optimal in code.
Imagine it like someone suggesting (understandably) that you express memory sizes in hex: no push to make everybody stop using decimal numbers!
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.
> Radians really are the natural unit for trigonometry.
s/trigonometry/calculus
The problem with this is that when I see pi I know we're talking about an angle; when you use turns it's just some number. Maybe in typed languages it would work better.
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.
Please stick to radians.
Posit arithmetic requires not only sin(x), but also sin(2πx), correctly rounded that is. I wish IEEE floats had that as well.
https://posithub.org/docs/posit_standard-2.pdf
Fails to mention that radians relates angle to arc length.
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.
Your awareness of a key relationship does not make it irrelevant. It happens all the time in math.
the article acts like radians are arbitrary without discussing this key property.
Even better : did you know (-1)^x draws the unit circle in the complex plane ? No need for complex exp and i*pi
That's because
That's equivalent to saying, no need for -1 because we have exp.
One can change based of the exponentiation operation. Exp happens to be a convenient base.
Yeah bad formulation on my part
Not bad at all, just equivalent.
We do need complex exp to define my formula, you’re right
If you plot it over which domain?
Complex domain
You do in fact need the complex exponential to define this correctly because the function a^x for nonintegers x is only unambiguously defined when a is a positive real number. For example, your function could be either e^(pi i x) or e^(-pi i x), which trace the circle in opposite directions as x varies over the reals. (They happen to agree when x is an integer.)
I agree. I just meant the 2D function cos(pix),sin(pix) is quite natural to work with and it can be reflected easily in the formulation of (-1)^x
Are there any c/c++ libs / headers that use this (without converting to radians in the background). I like this idea.
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
In the old days of making 8 bit video games we used BRADs of 0-255 - worked well and the wrap was easy.
Oh yeah, in the era of ¼ circle trig tables (cos and maybe tan; inverse (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.
Here's another good reason to think in turns: it turns Euler's formula from this Eldritch Terror:
into something you can kinda understand by staring at the complex plane:
Credit to justinpombrio for this: https://news.ycombinator.com/item?id=32986869
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.
I'll defend i^4x since I like it better.
(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)
Now define exponentiation by a non-integer.
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.
..which is a result of the more general formula.
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".
It got rid of pi and e, which already seems 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
> 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 mean, it's just shifting the value conversion in the other direction, isn't it?
Pi is a naturally-emerging concept: it's the ratio of a circle's circumference to its diameter. It just so happens that a lot of useful stuff we do in math operate on that ratio, not on either on the individual values (at least, not those alone).
I was hoping for some code examples but got none. Can anyone help?
> There are many implementations of sin, but no matter which one you look at…
I’ve had a brief moment of hope, forgetting the point was about mathematics.
Maybe related
Hamilton's theory of turns revisited
https://arxiv.org/abs/0904.4787
The title should say (2022)
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.
Indeed, this is what Pico-8 uses for its trigonometric functions[1] (angles go from 0 to 1, instead of from 0 to 2*Pi). I was surprised by this at first, but then I found it is very convenient and simplifies a bunch of stuff.
http://pico8wiki.com/index.php?title=Sin
I'm not super versed on the subject, but I think there's a case where using radians allows you to do direct multiplication without any conversion when trig isn't even involved, for rotation or transformation matrices? In which case this would fall apart rather completely if that doesn't work anymore and wouldn't be any different than switching to degrees, a convenience fix that requires conversion anyway.
Wait until you discover gradians: centesimal system applied to angles. A turn is 400 gradians, right angles are 100 gradians.
Same advantages as here but multiplied times 400...
You could even pick a highly compound number like 2^3*3^2*5 then you could divide it neatly into whole numbers for lots of divisors!
It's similar to why taxicab distance is better for distance measurement on limited hardware where sqrt() costs precious cycles. The reason to use sin() though is because it's a lookup table (where it counts) and not a bit of math, so moving to turns isn't necessarily a win.
At least we got metric units out of the French Revolution.
Gradians exist because "let's change everything, even things that aren't broken".
Norman Wildberger has an alternative system for trigonomtry:
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...
Turn is a measurement unit, and measurement units are just numbers. So turn ≈ 6.28318530718. You're welcome.
That should put to bed that whole τ crap. "But the symbol τ is used for other things!" Yeah, yeah, yeah, just write turn. Even better, because it's more international and has more precedent, write rev for revolution.