Я пытаюсь сделать функцию для округления числа с плавающей запятой до определенной длины цифр. То, что я придумал до сих пор это:Округление до определенного количества цифр в Haskell
import Numeric;
digs :: Integral x => x -> [x] <br>
digs 0 = [] <br>
digs x = digs (x `div` 10) ++ [x `mod` 10]
roundTo x t = let d = length $ digs $ round x <br>
roundToMachine x t = (fromInteger $ round $ x * 10^^t) * 10^^(-t)
in roundToMachine x (t - d)
Я использую функцию digs
, чтобы определить количество цифр до запятой, чтобы оптимизировать входное значение (то есть переместить все мимо запятой, так 1.234
становится 0.1234 * 10^1
)
Функция roundTo
работает для большинства входных сигналов, однако для некоторых входов я получаю странные результаты, например roundTo 1.0014 4
производит 1.0010000000000001
вместо 1.001
.
Проблема в этом примере вызывается путем вычисления 1001 * 1.0e-3
(который возвращает 1.0010000000000001
)
Является ли это просто проблема в представлении чисел в Haskell, я должен жить с или есть лучший способ обогнуть с плавающей точкой число до определенной длины цифр?
Я предполагаю, что вы знаете, что 0.1 является иррациональным у основания два, и будет _ всегда быть представлено неточно?Если вы хотите округлить до заданного количества десятичных знаков, вам потребуется десятичное представление, такое как строка. – 9000
Обратите внимание, что это не факт Haskell, тождественное поведение будет найдено на всех языках, если вы не имеете дело с [произвольными типами точности] (https://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic), которые редко * по умолчанию. Добро пожаловать в страшную часть о работе с финансовыми расчетами в программном обеспечении. –