For some reason, the map function returns a list that has one more
element than my input list. My input list is a range defined by [0, 60..359] (should translate into [0,60,120,180,240,300]). The function I'm giving to map is defined this way: ----- degreesToRadians :: Double -> Double degreesToRadians degrees = degrees * (pi / 180) ----- This is how I'm calling map overall: ----- > map degreesToRadians [0,60..359] [0.0,1.0471975511965976,2.0943951023931953,3.141592653589793,4.1887902047863905,5.235987755982989,6.283185307179586 ] ----- As you can hopefully see, there are seven elements instead of six. Getting the length confirms this: ----- > length [0,60..359] 6 > length $ map degreesToRadians [0,60..359] 7 ----- I do not seem to get this behaviour with the length if I either substitute the degreesToRadians function or substitute the [0,60..359] range. P.S. Is there a built-in function to convert degrees to radians and vice-versa? |
On Wed, 17 Jun 2009 23:35:23 +0200, Aaron MacDonald <[hidden email]>
wrote: > > This is how I'm calling map overall: > ----- > > map degreesToRadians [0,60..359] > [0.0,1.0471975511965976,2.0943951023931953,3.141592653589793,4.1887902047863905,5.235987755982989,6.283185307179586 > ] > ----- > > As you can hopefully see, there are seven elements instead of six. > Getting the length confirms this: > ----- > > length [0,60..359] > 6 > > length $ map degreesToRadians [0,60..359] > 7 > ----- Enumeration works differently for Double: Prelude> [0, 60..359 :: Double] [0.0,60.0,120.0,180.0,240.0,300.0,360.0] Prelude> length [0, 60..359 :: Double] 7 -- Met vriendelijke groet, Henk-Jan van Tuyl -- http://functor.bamikanarie.com http://Van.Tuyl.eu/ -- |
In reply to this post by Aaron MacDonald
Aaron,
Look at the following snippet: > length ([0,60..359] :: [Double]) 7 Basically, the Enum instance for Double is done differently than for Int (I don't remember why exactly). If you take off the type signature, it uses Int by default. When you use map, it implicitly converts that to a Double. Hope that helps. Michael On Thu, Jun 18, 2009 at 12:35 AM, Aaron MacDonald <[hidden email]>wrote: > For some reason, the map function returns a list that has one more element > than my input list. > > My input list is a range defined by [0, 60..359] (should translate into > [0,60,120,180,240,300]). > > The function I'm giving to map is defined this way: > ----- > degreesToRadians :: Double -> Double > degreesToRadians degrees = degrees * (pi / 180) > ----- > > This is how I'm calling map overall: > ----- > > map degreesToRadians [0,60..359] > > [0.0,1.0471975511965976,2.0943951023931953,3.141592653589793,4.1887902047863905,5.235987755982989,6.283185307179586] > ----- > > As you can hopefully see, there are seven elements instead of six. Getting > the length confirms this: > ----- > > length [0,60..359] > 6 > > length $ map degreesToRadians [0,60..359] > 7 > ----- > > I do not seem to get this behaviour with the length if I either substitute > the degreesToRadians function or substitute the [0,60..359] range. > > P.S. Is there a built-in function to convert degrees to radians and > vice-versa? > _______________________________________________ > Beginners mailing list > [hidden email] > http://www.haskell.org/mailman/listinfo/beginners > An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090617/cc915786/attachment.html |
In reply to this post by Henk-Jan van Tuyl
Sigh.
Well, what I was trying to do was get all angles in the range [0, 360) that have 60 degrees between them, since I'm going to be working with hexagons. I figured I'd use a range instead of hard-coded angles in case I wanted to use other shapes. Thanks, Aaron On 17-Jun-09, at 6:58 PM, Henk-Jan van Tuyl wrote: > On Wed, 17 Jun 2009 23:35:23 +0200, Aaron MacDonald <[hidden email] > > wrote: > >> >> This is how I'm calling map overall: >> ----- >> > map degreesToRadians [0,60..359] >> [0.0,1.0471975511965976,2.0943951023931953,3.141592653589793,4.1887902047863905,5.235987755982989,6.283185307179586 >> ] >> ----- >> >> As you can hopefully see, there are seven elements instead of six. >> Getting the length confirms this: >> ----- >> > length [0,60..359] >> 6 >> > length $ map degreesToRadians [0,60..359] >> 7 >> ----- > > Enumeration works differently for Double: > Prelude> [0, 60..359 :: Double] > [0.0,60.0,120.0,180.0,240.0,300.0,360.0] > Prelude> length [0, 60..359 :: Double] > 7 > > > -- > Met vriendelijke groet, > Henk-Jan van Tuyl > > > -- > http://functor.bamikanarie.com > http://Van.Tuyl.eu/ > -- > > |
In reply to this post by Aaron MacDonald
That's because [0,60,..359] is not the same as [0,60..359] ::
[Double]. So what you're passing to degreesToRadians is [0.0,60.0,120.0,180.0,240.0,300.0,360.0] and not [0,60,120,180,240,300]. I don't know why the Double version adds another number, though. On Jun 17, 2009, at 4:35 PM, Aaron MacDonald wrote: > For some reason, the map function returns a list that has one more > element than my input list. > > My input list is a range defined by [0, 60..359] (should translate > into [0,60,120,180,240,300]). > > The function I'm giving to map is defined this way: > ----- > degreesToRadians :: Double -> Double > degreesToRadians degrees = degrees * (pi / 180) > ----- > > This is how I'm calling map overall: > ----- > > map degreesToRadians [0,60..359] > [0.0,1.0471975511965976,2.0943951023931953,3.141592653589793,4.1887902047863905,5.235987755982989,6.283185307179586 > ] > ----- > > As you can hopefully see, there are seven elements instead of six. > Getting the length confirms this: > ----- > > length [0,60..359] > 6 > > length $ map degreesToRadians [0,60..359] > 7 > ----- > > I do not seem to get this behaviour with the length if I either > substitute the degreesToRadians function or substitute the > [0,60..359] range. > > P.S. Is there a built-in function to convert degrees to radians and > vice-versa? > _______________________________________________ > Beginners mailing list > [hidden email] > http://www.haskell.org/mailman/listinfo/beginners |
I think I understand the reason why, but still I find it disturbing that in
this first expression, x has 6 elements: Prelude> let x = [0,60..359]; y = [0,60..359] in (x, y, map degreesToRadians y) ([0,60,120,180,240,300],[0.0,60.0,120.0,180.0,240.0,300.0,360.0],[0.0,1.0471975333333332,2.094395066 6666664,3.1415926,4.188790133333333,5.235987666666667,6.2831852]) But if I add a comparison to y, x now has 7 elements: Prelude> let x = [0,60..359]; y = [0,60..359] in (x, y, map degreesToRadians y, *x==y*) ([0.0,60.0,120.0,180.0,240.0,300.0,360.0],[0.0,60.0,120.0,180.0,240.0,300.0,360.0],[0.0,1.0471975333 333332,2.0943950666666664,3.1415926,4.188790133333333,5.235987666666667,6.2831852],True) I. J. Kennedy On Wed, Jun 17, 2009 at 4:55 PM, Alan Mock <[hidden email]> wrote: > That's because [0,60,..359] is not the same as [0,60..359] :: [Double]. So > what you're passing to degreesToRadians is > [0.0,60.0,120.0,180.0,240.0,300.0,360.0] and not [0,60,120,180,240,300]. I > don't know why the Double version adds another number, though. > > > On Jun 17, 2009, at 4:35 PM, Aaron MacDonald wrote: > > For some reason, the map function returns a list that has one more element >> than my input list. >> >> My input list is a range defined by [0, 60..359] (should translate into >> [0,60,120,180,240,300]). >> >> The function I'm giving to map is defined this way: >> ----- >> degreesToRadians :: Double -> Double >> degreesToRadians degrees = degrees * (pi / 180) >> ----- >> >> This is how I'm calling map overall: >> ----- >> > map degreesToRadians [0,60..359] >> >> [0.0,1.0471975511965976,2.0943951023931953,3.141592653589793,4.1887902047863905,5.235987755982989,6.283185307179586] >> ----- >> >> As you can hopefully see, there are seven elements instead of six. Getting >> the length confirms this: >> ----- >> > length [0,60..359] >> 6 >> > length $ map degreesToRadians [0,60..359] >> 7 >> ----- >> >> I do not seem to get this behaviour with the length if I either substitute >> the degreesToRadians function or substitute the [0,60..359] range. >> >> P.S. Is there a built-in function to convert degrees to radians and >> vice-versa? >> _______________________________________________ >> Beginners mailing list >> [hidden email] >> http://www.haskell.org/mailman/listinfo/beginners >> > > _______________________________________________ > Beginners mailing list > [hidden email] > http://www.haskell.org/mailman/listinfo/beginners > An HTML attachment was scrubbed... URL: http://www.haskell.org/pipermail/beginners/attachments/20090618/32f60c05/attachment.html |
Am Donnerstag 18 Juni 2009 15:24:20 schrieb Jack Kennedy:
> I think I understand the reason why, but still I find it disturbing that in > this first expression, x has 6 elements: > > Prelude> let x = [0,60..359]; y = [0,60..359] in (x, y, map > degreesToRadians y) You give no type for x, so the default is chosen, that is Integer. The expression map degreesToRadians y forces y to have type [Double] (you could give y a more general type if you specified a type signature). > ([0,60,120,180,240,300],[0.0,60.0,120.0,180.0,240.0,300.0,360.0],[0.0,1.047 >1975333333332,2.094395066 > 6666664,3.1415926,4.188790133333333,5.235987666666667,6.2831852]) > > But if I add a comparison to y, x now has 7 elements: > > Prelude> let x = [0,60..359]; y = [0,60..359] in (x, y, map > degreesToRadians y, *x==y*) > ([0.0,60.0,120.0,180.0,240.0,300.0,360.0],[0.0,60.0,120.0,180.0,240.0,300.0 >,360.0],[0.0,1.0471975333 > 333332,2.0943950666666664,3.1415926,4.188790133333333,5.235987666666667,6.2 >831852],True) Now, the expression x==y forces x to have the same type as y, which still is [Double]. But, lo and behold: Prelude> let degreesToRadians :: Double -> Double; degreesToRadians d = d*pi/180 Prelude> let x :: (Num a, Enum a) => [a]; x = [0, 60 .. 359]; y :: (Num a, Enum a) => [a]; y = [0, 60 .. 359] Prelude> (x,y,map degreesToRadians y, x == y) ([0,60,120,180,240,300],[0,60,120,180,240,300], [0.0,1.0471975511965976,2.0943951023931953,3.141592653589793,4.1887902047863905,5.235987755982989,6.283185307179586],True) > > I. J. Kennedy > |
Check this out:
Prelude> [0,60..330]::[Double] [0.0,60.0,120.0,180.0,240.0,300.0,360.0] Prelude> [0,60..329]::[Double] [0.0,60.0,120.0,180.0,240.0,300.0] It looks like the decision the step to the next value in case of flt. point enumeration depends on >= enumWith / 2. But that should be answered by those who know from under the hood. -- Met vriendelijke groet, =@@i |
On Thu, Jun 18, 2009 at 05:32:26PM +0200, Aai wrote:
> Check this out: > > Prelude> [0,60..330]::[Double] > [0.0,60.0,120.0,180.0,240.0,300.0,360.0] > > Prelude> [0,60..329]::[Double] > [0.0,60.0,120.0,180.0,240.0,300.0] > > It looks like the decision the step to the next value in case of flt. > point enumeration depends on >= enumWith / 2. But that should be > answered by those who know from under the hood. That is correct. The reason for this is because of the inaccuracy of floating point numbers. For example, consider [0.1,0.2..10.0] which clearly ought to contain 100 numbers, every tenth from 0.1 through 10.0 inclusive. But 0.1 cannot be represented exactly in binary, so adding 0.1 to itself 100 times might very well give a result like 10.0000000002. Should this be included in the range, or not? After all, it's bigger than 10.0...but it would be quite surprising if the 10.0000000002 were left out. Hence the last number is included even if it is up to 1/2 of a step over the end value of the range. But this can also be surprising at times (as the original poster found out!). What to do? The answer is: don't use list enumerations for floating point numbers!! It is nonsensical. Alternative options include: * use Rational instead of Double, which IS exact * use Integers for the enumeration, and then convert to Double and so on. -Brent |
Free forum by Nabble | Edit this page |