Live data from Hacker News

Turns are better than radians

computerenhance.com

441–450 of 494 posts

Re: Turns are better than radians

#441

Earlier quoted context omitted.

That's a nice result. 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. Huge selling point for turns, IMHO.

>Huge selling point for turns, IMHO. Ok, then let’s measure angles in quarter -turns! Then the equation becomes even nicer: i^x = cos(x) + isin(x) Beautiful! :-0 Except not. Because you’re obscuring the connection of sin/cos with their hyperbolic counterparts. I.e. this is no longer true: sinh(x) = -isin(ix) cosh(x) = cos(ix) Also, this new convention obscures the connection with the exponential map of Lie groups. I.…

> Because you’re obscuring the connection of sin/cos with their hyperbolic counterparts.

Only because we forgot the name change: these are supposed to to be nsin and ncos.

Remember also that people use sin and cos with 360-degree degrees just fine; and don't worry about wrecking the connection to the hyperbolic counterparts --- and without changing the names, either.

Re: Turns are better than radians

#443

On the frontend, one thing that I discovered when implementing color spaces into my canvas library was that the CSS HWB standard[1] allows the hue part of a color (which is an angle value) to be supplied supplied as either 'Ndeg', 'Nrad', 'Ngrad' or 'Nturn' values. Other CSS color spaces involving hue don't see to accept 'turn' (though I could be misunderstanding them). [1] - https://developer.mozilla.org/en-US/docs/…

You’re misunderstanding things. CSS is typed, and deg/rad/grad/turn are all just angle units; anything that takes an supports angles in any unit. hsl(0.5turn 100% 50%) is equivalent to hsl(180deg 100% 50%) and #00ffff (and infinite other spellings).

When it was introduced, hsl() only took a for hue, which was interpreted as degrees, but it has had proper support for over a decade (apart from Opera which only got it with the switch to Chromium in 2013). The current state of affairs is ` = | | none` (https://drafts.csswg.org/css-color-4/#hue-syntax), and is used by hsl(), hsla(), hwb(), lch() and oklch().

Re: Turns are better than radians

#444
post #396

Earlier quoted context omitted.

>The actual equation you come to for ncos an nsin is: >(-1)^(2x) = ncos(x) + i nsin(x) Try to formally define this procedure, though. You end up going in circles. Here's another version: lim[N->infinity] (1 + ix/N)^N = cos(x) + i sin(x) Now there are no "weird numbers", and both sides of the equation can be calculated directly , even by hand if you wanted. If all you're teaching students is a bunch of formulas to be…

> Try to formally define this procedure, though. You end up going in circles. The cos(x) + isin(x) formula gives us a way to find the point on the complex plane's unit circle corresponding to an angle x, given in radians. (Plus it does more, because the argument is complex valued.) The new formula with ncos and nsin does the same thing for an angle given in turns. E.g 0.25 (90 degrees): -1^(0.5) = i. It's understanda…

>It's understandable in terms of roots of -1.

You seem to have missed the point. You need the formula I gave to rigorously compute the roots of -1. Of course, you could notice that (cos(x) + i sin(x))^n = cos(nx) + i sin(nx), but that's what I meant by "going in circles". You end up defining (-1)^x in terms of sines and cosines, making the "formula" trivial. It's difficult, working this way, to understand why (-1)^(1/3) is (1 + isqrt(3))/2 and not just -1.

By contrast, the Bernoulli formula is actually computable. In fact, the CORDIC algorithm corresponds quite closely to computing the Bernoulli formula by repeated squaring. The use of arctan(2^(-n)) is just like taking (1 + i2^(-n))^(2^n).

There's a reason why math is structured the way it is.

Re: Turns are better than radians

#445

Earlier quoted context omitted.

I think you're confusing "representation" to mean just the number of bits allocated to the number, but the article and my comments also use it to mean what the numeric range of those values represents (hence "representation"). How that's modeled in the static type system is completely orthogonal to the underlying arithmetic operations that are performed and their efficiency. The article is entirely about the latter.

No, I think you're confused about what I'm saying about performance. I definitely don't think "representation" just means the number of bits. > How that's modeled in the static type system is completely orthogonal to the underlying arithmetic operations that are performed and their efficiency. No! A type system gives information in in both directions. Normally yes, we use it to impose some interpretation on a represe…

I feel like we're talking past each other or the goal posts are moving or something.

> If we had reasonable types, sin could define the type it wants to do what it does efficiently (turns, or radians if the platform has an efficient instruction, or a lookup table index into some division of a quadrant, or whatever). That representation matters to the sin author, but not the user. All the user cares about is, then, how many times do I have to pay some conversion cost? And if I'm using the type the sin author provided, the answer is zero (or maybe like one, at initial load). But that relies on the sin author using such a newtype.

Everything here is equally true if you take types entirely out. sin() will ultimately be doing math on floating point values. The sin() function expects angles according to a specified scale. Some scales (turns, according to the author) require one less multiplication in the function prelude. Therefore, sin() is faster if it specifies that as the input scale.

That benefit is negated if angles are stored in another scale and rescaled every time sin() is called. That's just hoisting the multiplication out to every callsite.

So what you need is to store angles in the numeric scale that is fastest for the implementation of sin().

Whether those floating point angles are wrapped in a newtype is completely orthogonal. What matters is that the numeric scale you use to store and represent angles is the one that requires the least arithmetic in the underlying implementation of the trig functions.

Unit types are great, but they solve different problems than the article is talking about.

Re: Turns are better than radians

#446

Earlier quoted context omitted.

> Degrees are completely arbitrary Degrees are very natural in the context of ancient astronomy/astrology, where you have (1) ~365 days in a year, so that if you look at the path of something that takes a year you get about one degree change per day but with a number that is more easily divisible. (2) approximately 4y, 10y, 8y, 15y, 12y, 30y cycles for the moon and various planets. (3) A calendar with 12 months, 12 z…

All those approximations have error and the behaviour you describe depends on where you are on Earth. Moreover, degrees are not natural from a mathematical perspective.

Out of curiosity, given a degree/calendar/time system could one localize the culture that created it?

Re: Turns are better than radians

#447

Better than turns, radians, etc. is an `Angle` newtype AKA wrapper class. It completely eliminates misinterpretation of the value, miscalculation from [angle = angle + tau*n] as all angles are normalized, is more descriptive, and in a decent language is zero-cost. Programmers should not be using (radians: float) in modern languages which support wrapper classes

But what is the underlying representation in the wrapper class?

you can have an internal representation enum and when calling

sin(Angle a){ switch a.representation: rad : sin(a.rad); turn: nsin(a.turn) }

conversion only needed when adding angles of different representation.

Re: Turns are better than radians

#448

There are a lot of comments here saying that radians are the only true way to deal with angles, however I agree with the author of the original article that turns are a legitimate alternative - I just wouldn't use the same language. Instead I would say that the new function I'm calculating is sin(2π t), and maybe also say that t is measured in turns, where (1 turn) = (2π rad). It still has a nice small angle approxim…

that's a nice naming convention too,

everyone understands that calling

sin2π(x) = sin(2π * x)

Re: Turns are better than radians

#449

Earlier quoted context omitted.

I heard that the reason is 1km away it makes a difference of 1m, so easy to figure out how far enemy troops are from each other.

More importantly, it can be used for ranging. The average human height is known, and (usually) so are the sizes of whatever vehicles the other side might be using. Thus, when observing things of known size through some optic with a reticle graduated in mils, you can easily determine the range to them. Which then gives you e.g. the amount of holdover necessary to hit the target with a gun (which can itself be expresse…

Ah of course it is the other way around like you say. You know the size of things, you need to figure out the distance.

Re: Turns are better than radians

#450

Earlier quoted context omitted.

But what is the underlying representation in the wrapper class?

you can have an internal representation enum and when calling sin(Angle a){ switch a.representation: rad : sin(a.rad); turn: nsin(a.turn) } conversion only needed when adding angles of different representation.

Sounds like you're balancing out the performance gains the article talks about with performance losses from branching.
Post reply on HN