Home > Mobile >  sin function returning numbers outside of range [-1, 1]
sin function returning numbers outside of range [-1, 1]

Time:02-11

I am working in Haskell and have had an error where, for really large floats z, sin(z) returns some value outside of the range [-1, 1].

I'm learning Haskell for the first time, so I have had very little luck debugging and the program just crashes when sin(z) does return a value outside of the above range as sin(z) is an input into another function that only accepts values inside the range [-1, 1].

Additionally, I don't have access to the other function, I only can send in a value, but it keeps crashing when sin(z) returns a number either greater than 1 or less than -1.

Is there any way to figure out why sin(z) is doing this?

CodePudding user response:

The sin :: Double -> Double function returns a number strictly between -1 and 1 for all finite inputs, no matter how large. In particular, for the largest representable finite positive double, it returns a value that's roughly 0.005:

> sin (1.7976931348623157E 308 :: Double)
4.961954789184062e-3

and for the largest representable finite negative double, it returns a value that's the negative of that:

> sin (-1.7976931348623157E 308 :: Double)
-4.961954789184062e-3

What's undoubtedly happening is that your input to sin has exceeded the finite range of Double. For example, the following double isn't actually representable as a finite double and is "rounded" to infinity:

> 1.7976931348623159E 308 :: Double
Infinity

If you feed such an infinite value to sin, you get NaN:

> sin (1.7976931348623159E 308 :: Double)
NaN

which will undoubtedly cause problems when fed to a function expecting finite numbers between -1 and 1. This can be "fixed" with min:

> min (sin (1.7976931348623159E 308 :: Double)) 1
1.0

but this fix is largely useless because you have a much bigger problem going on.

For numbers this large, the precision of a Double is on the order of plus or minus 1e292. That is, two "adjacent" representable finite doubles of this size are about 1e292 apart and the sin of two such numbers might as well be random numbers between -1 and 1, completely unrelated to any calculation you're trying to complete. Whatever you're trying to do with these numbers can't possibly be working as you intend.

CodePudding user response:

It seems like this is a floating point error; see this similar post. So for very large values, the sin function is returning a value slightly above 1, due to rounding errors.

To solve your problem, I would cap the return value at 1. Specifically, return the min 1 (sin z) instead of just the sin z directly.

Edit: replaced max with min.

  • Related