Re: [Python-ideas] Trigonometry in degrees

On Fri, Jun 08, 2018 at 10:53:34AM +0200, Adam Bartoš wrote:
Wouldn't sin(45 * DEG) where DEG = 2 * math.pi / 360 be better that sind(45)? This way we woudn't have to introduce new functions. (The
Steven D'Aprano wrote: problem
with nonexact results for nice angles is a separate issue.)
But that's not a separate issue, that's precisely one of the motives for having dedicated trig functions for degrees.
sind(45) (or dsin(45), as I would prefer) could (in principle) return the closest possible float to sqrt(2)/2, which sin(45*DEG) does not do:
py> DEG = 2 * math.pi / 360 py> math.sin(45*DEG) == math.sqrt(2)/2 False
Likewise, we'd expect cosd(90) to return zero, not something not-quite zero:
py> math.cos(90*DEG) 6.123031769111886e-17
That's how it works in Julia:
julia> sind(45) == sqrt(2)/2 true
julia> cosd(90) 0.0
and I'd expect no less here. If we can't do that, there probably wouldn't be much point in the exercise.
But if there are both sin and dsin, and you ask about the difference between them, the obvious answer would be that one takes radians and the other takes degrees. The point that the degrees version is additionally exact on special values is an extra benefit. It would be nice to also fix the original sin, or more precisely to provide a way to give it a fractional multiple of pi. How about a special class PiMultiple that would represent a fractional multiple of pi? PI = PiMultiple(1) assert PI / 2 == PiMultiple(1, 2) assert cos(PI / 2) == 0 DEG = 2 * PI / 360 assert sin(45 * DEG) == sqrt(2) / 2 Best regards, Adam Bartoš

On 6/8/18 5:11 PM, Adam Bartoš wrote:
On Fri, Jun 08, 2018 at 10:53:34AM +0200, Adam Bartoš wrote:
Wouldn't sin(45 * DEG) where DEG = 2 * math.pi / 360 be better that sind(45)? This way we woudn't have to introduce new functions. (The
Steven D'Aprano wrote: problem
with nonexact results for nice angles is a separate issue.)
But that's not a separate issue, that's precisely one of the motives for having dedicated trig functions for degrees.
sind(45) (or dsin(45), as I would prefer) could (in principle) return the closest possible float to sqrt(2)/2, which sin(45*DEG) does not do:
py> DEG = 2 * math.pi / 360 py> math.sin(45*DEG) == math.sqrt(2)/2 False
Likewise, we'd expect cosd(90) to return zero, not something not-quite zero:
py> math.cos(90*DEG) 6.123031769111886e-17
That's how it works in Julia:
julia> sind(45) == sqrt(2)/2 true
julia> cosd(90) 0.0
and I'd expect no less here. If we can't do that, there probably wouldn't be much point in the exercise.
But if there are both sin and dsin, and you ask about the difference between them, the obvious answer would be that one takes radians and the other takes degrees. The point that the degrees version is additionally exact on special values is an extra benefit. It would be nice to also fix the original sin, or more precisely to provide a way to give it a fractional multiple of pi. How about a special class PiMultiple that would represent a fractional multiple of pi?
PI = PiMultiple(1) assert PI / 2 == PiMultiple(1, 2) assert cos(PI / 2) == 0 DEG = 2 * PI / 360 assert sin(45 * DEG) == sqrt(2) / 2
Best regards, Adam Bartoš
In one sense that is why I suggest a Circle based version of the trig functions. In effect that is a multiple of Tau (= 2*pi) routine. Richard Damon

On Fri, Jun 08, 2018 at 11:11:09PM +0200, Adam Bartoš wrote:
But if there are both sin and dsin, and you ask about the difference between them, the obvious answer would be that one takes radians and the other takes degrees. The point that the degrees version is additionally exact on special values is an extra benefit.
No, that's not an extra benefit, it is the only benefit! If we can't make it exact for the obvious degree angles, there would be no point in doing this. We'd just tell people to write their own two-line functions: def sindeg(angle): return math.sin(math.radians(angle)) The only reason to even consider making this a standard library function is if we can do better than that.
It would be nice to also fix the original sin,
The sin function is not broken and does not need fixing. (Modulo quirks of individual platform maths libraries.)
or more precisely to provide a way to give it a fractional multiple of pi. How about a special class PiMultiple that would represent a fractional multiple of pi?
What is the point of that? When you pass it to math.sin, it still needs to be converted to a float before sin can operate on it. Unless you are proposing a series of dunder methods __sin__ __cos__ and __tan__ to allow arbitrary classes to be passed to sin, cos and tan, the following cannot work:
PI = PiMultiple(1) assert PI / 2 == PiMultiple(1, 2) assert cos(PI / 2) == 0
Without a __cos__ dunder method that allows PiMultiple objects to customise the result of cos(), that last line has to fail, because cos(math.pi/2) == 0 fails.
DEG = 2 * PI / 360 assert sin(45 * DEG) == sqrt(2) / 2
Likewise. -- Steve
participants (3)
-
Adam Bartoš
-
Richard Damon
-
Steven D'Aprano