Odd values ​​when listing a list

As part of a larger definition of a function, I needed to let the domain (i, n) of the function increase from i to n at different speeds. Therefore, I wrote:

f (i, n) k = [i, (i+k)..n]

in the ghc. This led to odd results:

*Main> f (0.0, 1.0) 0.1
[0.0,0.1,0.2,0.30000000000000004,0.4000000000000001,0.5000000000000001,0.6000000000000001,0.7000000000000001,0.8,0.9,1.0]

Why is the GHC returned, for example, 0.30000000000000004 instead of 0.3?

+3
source share
3 answers

If i, n and k are rational, you can go the route with infinite accuracy:

f :: (Rational, Rational) -> Rational -> [Rational]
f (i, n) k = [i, (i+k) .. n]

It may take some time to indicate:

ghci> f (0% 1, 1% 1) (1% 10)
[0% 1.1% 10.1% 5.3% 10.2% 5.1% 2.3% 5.7% 10.4% 5.9% 10.1% 1]

Think of %how fun a faction bar is.

You can view the approximations using

import Control.Monad (mapM_)
import Data.Ratio (Rational, (%), denominator, numerator)
import Text.Printf (printf)

printApprox :: [Rational] -> IO ()
printApprox rs = do
  mapM_ putRationalToOnePlaceLn rs
  where putRationalToOnePlaceLn :: Rational -> IO ()
        putRationalToOnePlaceLn r = do
          let toOnePlace :: String
              toOnePlace = printf "%.1f" (numFrac / denomFrac)
              numFrac, denomFrac :: Double
              numFrac    = fromIntegral $ numerator   r
              denomFrac  = fromIntegral $ denominator r
          putStrLn toOnePlace

. -. mapM_ Control.Monad (putRationalToOnePlaceLn ) ( ). for, forM_, mapM_ . Haskell, , , mapM forM, .

putStrLn, . C,

int numerator = 1, denominator = 10;
printf("%.1f\n", (double) numerator / (double) denominator);

Haskell, , . Haskell /

(/) :: (Fractional a) => a -> a -> a

a typeclass Fractional, a, .

ghci Fractional:

ghci> :info Fractional
class (Num a) => Fractional a where
  (/) :: a -> a -> a
  recip :: a -> a
  fromRational :: Rational -> a
    -- Defined in GHC.Real
instance Fractional Float -- Defined in GHC.Float
instance Fractional Double -- Defined in GHC.Float

instance . ,

ghci> (22::Float) / (7::Float)
3.142857

ghci> (22::Double) / (7::Double)
3.142857142857143

ghci> (22::Double) / (7::Float)

<interactive>:1:16:
    Couldn't match expected type `Double' against inferred type `Float'
    In the second argument of `(/)', namely `(7 :: Float)'
    In the expression: (22 :: Double) / (7 :: Float)
    In the definition of `it': it = (22 :: Double) / (7 :: Float)

, ,

ghci> (22::Integer) / (7::Integer)

<interactive>:1:0:
    No instance for (Fractional Integer)
      arising from a use of `/' at :1:0-27
    Possible fix: add an instance declaration for (Fractional Integer)
    In the expression: (22 :: Integer) / (7 :: Integer)
    In the definition of `it': it = (22 :: Integer) / (7 :: Integer)

, Haskell Rational Integers, fromIntegral C.

Haskell: Numbers, Haskell, . , , , . - .

:

*Main> printApprox $ f (0%1, 1%1) (1%10)
0.0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
1.0

printApprox, , , . , Haskell, .

Haskell - : , , , . - , Haskell , Perl .

point-free style , . , , , .

,

import Control.Arrow ((***), (&&&))
import Control.Monad (join, mapM_)
import Data.Ratio (Rational, (%), denominator, numerator)
import Text.Printf (printf)

printApproxPointFree :: [Rational] -> IO ()
printApproxPointFree =
  mapM_       $
  putStrLn    .
  toOnePlace  .
  uncurry (/) .
  join (***) fromIntegral .
  (numerator &&& denominator)
  where toOnePlace = printf "%.1f" :: Double -> String

: mapM_, putStrLn, printf, numerator denominator.

. Haskell $ - -.

f $ x = f x

,

Prelude> show 1.0 / 2.0

<interactive>:1:0:
    No instance for (Fractional String)
      arising from a use of `/' at :1:0-13
    Possible fix: add an instance declaration for (Fractional String)
    In the expression: show 1.0 / 2.0
    In the definition of `it': it = show 1.0 / 2.0

show (1.0 / 2.0)

show $ 1.0 / 2.0

, $ .

., .

(f . g) x = f (g x)

(f . g) x = f $ g x

, , . ,

rendered composition example

. .

, , , .

(numerator &&& denominator) Control.Arrow. :

ghci> (numerator &&& denominator) $ 1%3
(1,3)

, . , fromIntegral , , join (***) fromIntegral. , *** Control.Arrow.

, / , . , -

(fst tuple) / (snd tuple)

fst (a,_) = a
snd (_,b) = b

! , - / , ? , uncurry (/) !

Haskell. !

+4

IEEE , . , .

, GHC , , Windows 0.3. , Microsoft , Linux Mac, , float.

EDIT: . 0.3 3fd3333333333333 IEEE , 0.1 + 0.1 + 0.1 , 3fd3333333333334, , Microsoft , 0.3 .

0.3 Python. Python 2.6, 0.29999999999999999, 2.7, 0.3.

+9

The best way to do this is more line by line

map (/10) [0 .. 10]

This takes integers, thereby avoiding float problems and dividing each by 10.

+2
source

Source: https://habr.com/ru/post/1754082/


All Articles