Converting numbers
From HaskellWiki
(realToFrac) |
(→Converting between float types. Replace confusing stuff with something simple that works.) |
||
| (One intermediate revision not shown.) | |||
| Line 35: | Line 35: | ||
Say, conversion from Float to Double and back. | Say, conversion from Float to Double and back. | ||
| - | * <hask> | + | * <hask>import GHC.Float</hask> |
| - | * <hask> | + | * <hask>:t float2Double</hask> |
| + | * <hask>float2Double :: Float -> Double</hask> | ||
| + | * <hask>:t double2Float</hask> | ||
| + | * <hask>double2Float :: Double -> Float</hask> | ||
== Automatic conversion == | == Automatic conversion == | ||
| Line 42: | Line 45: | ||
Repeatedly people ask for automatic conversion between numbers. This is usually not a good idea; for more information, refer to the thoughts about a [[Generic number type]]. | Repeatedly people ask for automatic conversion between numbers. This is usually not a good idea; for more information, refer to the thoughts about a [[Generic number type]]. | ||
| - | == | + | == Example == |
| - | Hi, I am trying to write some | + | Hi, I am trying to write some functions that convert between two coordinate systems. The first coordinate system, which ill call coord1, starts in the upper left at (0, 0) and ends in the lower right at (500, 500). Coordinates in coord1 have type (Int, Int). The second coord system, which I'll call coord2, starts in the lower left at (0.0, 0.0) and ends in the upper right at (1.0, 1.0). Coords in coord2 have type (Float, Float). I was hoping someone could help me figure out how I can rewrite the two functions below so that the type checker will accept them. |
<haskell> | <haskell> | ||
coord1ToCoord2 :: (Int, Int) -> (Float, Float) | coord1ToCoord2 :: (Int, Int) -> (Float, Float) | ||
| Line 64: | Line 67: | ||
coord2ToCoord1 (1.0, 1.0) -> (500, 0) | coord2ToCoord1 (1.0, 1.0) -> (500, 0) | ||
</haskell> | </haskell> | ||
| - | + | One of the thing that confused me was that I expected 500 to be an Int, but in fact the literals are automatically converted to a correct Num instance. | |
| - | + | The solution here was to use fromIntegral and round : | |
<haskell> | <haskell> | ||
| - | + | coord1ToCoord2 :: (Int, Int) -> (Float, Float) | |
| - | + | coord1ToCoord2 (x, y) = (fromIntegral x/500, (500 - fromIntegral y)/500) | |
| - | + | ||
| - | + | coord2ToCoord1 :: (Float, Float) -> (Int, Int) | |
| - | + | coord2ToCoord1 (x, y) = (round (500 * x), round (500 - 500 * y)) | |
| - | + | ||
| - | + | ||
| - | + | ||
| - | + | ||
</haskell> | </haskell> | ||
| - | |||
[[Category:Mathematics]] | [[Category:Mathematics]] | ||
[[Category:FAQ]] | [[Category:FAQ]] | ||
[[Category:Idioms]] | [[Category:Idioms]] | ||
Current revision
Converting between numerical types in Haskell must be done explicitly. This is unlike languages (such as C or Java) which automatically cast between numerical types in certain situations.
Contents |
1 Converting from integers and between integer types
Integral types are ones which may only contain whole numbers and not fractions.fromIntegral :: (Num b, Integral a) => a -> b
2 Converting to Rational
To convert something to atoRational :: (Real a) => a -> Rational
3 Converting to Integral
This is an inherently lossy transformation since integral types cannot express non-whole numbers. Depending on how you wish to convert, you might choose one of several methods.
- ceiling :: (RealFrac a, Integral b) => a -> b
- floor :: (RealFrac a, Integral b) => a -> b
- truncate :: (RealFrac a, Integral b) => a -> b
- round :: (RealFrac a, Integral b) => a -> b
4 Converting between float types
Say, conversion from Float to Double and back.
- import GHC.Float
- :t float2Double
- float2Double :: Float -> Double
- :t double2Float
- double2Float :: Double -> Float
5 Automatic conversion
Repeatedly people ask for automatic conversion between numbers. This is usually not a good idea; for more information, refer to the thoughts about a Generic number type.
6 Example
Hi, I am trying to write some functions that convert between two coordinate systems. The first coordinate system, which ill call coord1, starts in the upper left at (0, 0) and ends in the lower right at (500, 500). Coordinates in coord1 have type (Int, Int). The second coord system, which I'll call coord2, starts in the lower left at (0.0, 0.0) and ends in the upper right at (1.0, 1.0). Coords in coord2 have type (Float, Float). I was hoping someone could help me figure out how I can rewrite the two functions below so that the type checker will accept them.
coord1ToCoord2 :: (Int, Int) -> (Float, Float) coord1ToCoord2 (x, y) = (x/500, (500-y)/500) coord2ToCoord1 :: (Float, Float) -> (Int, Int) coord2ToCoord1 (x, y) = (500/(1/x), 500 - 500/(1/y))
examples of what i want. i think i have the logic right :)
coord1ToCoord2 (0, 0) -> (0.0, 1.0) coord1ToCoord2 (250, 250) -> (0.5, 0.5) coord1ToCoord2 (350, 350) -> (0.7, 0.3) coord1ToCoord2 (500, 500) -> (1.0, 0.0) coord2ToCoord1 (0.0, 0.0) -> (0, 500) coord2ToCoord1 (0.5, 0.5) -> (250, 250) coord2ToCoord1 (0.7, 0.7) -> (350, 150) coord2ToCoord1 (1.0, 1.0) -> (500, 0)
One of the thing that confused me was that I expected 500 to be an Int, but in fact the literals are automatically converted to a correct Num instance.
The solution here was to use fromIntegral and round :
coord1ToCoord2 :: (Int, Int) -> (Float, Float) coord1ToCoord2 (x, y) = (fromIntegral x/500, (500 - fromIntegral y)/500) coord2ToCoord1 :: (Float, Float) -> (Int, Int) coord2ToCoord1 (x, y) = (round (500 * x), round (500 - 500 * y))
Categories: Mathematics | FAQ | Idioms
