Как получить число с плавающей запятой непосредственно перед / после заданного числа в Haskell? - PullRequest
6 голосов
/ 29 сентября 2019

Учитывая Float или Double, как я могу получить следующий, больший или меньший?Другими словами, как выполнить функции, эквивалентные C ++ std::nextafter функциям ?Например, учитывая 0 :: Float, я бы хотел получить 1.40129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125e-45 (который show s как 1.0e-45) как следующий, больший, а учитывая 1 :: Float, я бы хотел получить 0.999999940395355224609375(который show s как 0.99999994) как следующий меньший.Если возможно, я хотел бы знать, как сделать это самому в Haskell, а не просто делать это с помощью сторонней библиотеки (хотя я в порядке с чем-то в base) или с помощью FFI для вызова этого C ++функция.

Ответы [ 2 ]

5 голосов
/ 29 сентября 2019

Вы можете использовать функцию succIEEE :: IEEE a => a -> a, которая будет использоваться для типа, принадлежащего классу типов IEEE (Float, Double, CFloat и CDouble принадлежат к этому классу типов) вычисляют следующее представимое число.Или как указано в документации:

Возвращает следующее наибольшее значение IEEE (бесконечность и NaN не изменяются).

Например:

Prelude Numeric.IEEE> succIEEE 0
5.0e-324
Prelude Numeric.IEEE> succIEEE 1
1.0000000000000002
Prelude Numeric.IEEE> succIEEE 0 :: Float
1.0e-45
Prelude Numeric.IEEE> succIEEE 1 :: Float
1.0000001
Prelude Numeric.IEEE> succIEEE (0 :: Float) == 1.40129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125e-45
True
3 голосов
/ 29 сентября 2019

Этот алгоритм был украден из mail.haskell.org/pipermail/haskell/2003-October/012931.html

import GHC.Float

nextafter1 :: Float -> Float
nextafter1 0 = 0
nextafter1 x | GHC.Float.isNaN x = x
nextafter1 x | GHC.Float.isInfinite x = x
nextafter1 x = try (abs x)
  where try d = let d1 = d/2
                in if x + d1 == x then improve d1 d else try d1
        improve a b = let middle = (a+b)/2
                      in if middle == b || middle == a 
                         then x + b
                         else if x + middle > x 
                              then improve a middle 
                              else improve middle b
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...