Поскольку 1.1
и 3.3
являются floating point numbers. Десятичные дробные числа, такие как .1 или .3, точно не представляются в двоичном числе с плавающей запятой. .1 означает 1/10. Чтобы представить это в двоичном формате, где каждая дробная цифра представляет 1/2 n (1/2, 1/4, 1/8 и т. Д.), Вам понадобится бесконечное число цифр, 0,000110011 ... повторяющееся бесконечно.
Это точно такая же проблема, как представление, например, 1/3 в основании 10. В базе 10 вам понадобится бесконечное количество цифр .33333 ... навсегда, чтобы точно представлять 1/3. Поэтому, работая в базе 10, вы обычно кружась, к чему-то вроде .33. Но если вы добавите три копии этого кода, вы получите .99, а не 1.
Для получения дополнительной информации по этой теме читайте What Every Computer Scientist Should Know About Floating Point Arithmetic.
Для представления рациональных чисел точнее в Haskell, вы всегда можете использовать рациональный тип данных, Ratio
; в сочетании с bignums (произвольно большие целые числа, Integer
в Haskell, в отличие от Int
, которые являются фиксированным размером) в качестве типа для числителя и знаменателя, вы можете представлять произвольно точные рациональные числа, но со значительно меньшей скоростью, чем числа с плавающей запятой, которые реализован в аппаратном обеспечении и оптимизирован для скорости.
Числа с плавающей запятой - это оптимизация для научных и вычислительных вычислений, которые преходят точность для высокой скорости, позволяя вам выполнить очень большое количество вычислений за небольшую паузу, если вы знаете о округлении и как это влияет на ваши вычисления.
Nice javascript float - decimal - бинарный визуализатор: http://babbage.cs.qc.edu/IEEE-754/Decimal.html – Seth
Это не проблема, связанная с Haskell: то же самое произойдет на любом языке, который использует числа с плавающей запятой. Точные детали зависят от реализации с плавающей запятой, но большинство процессоров используют IEEE-754, который строго указан для обеспечения того, что программы плохо себя ведут одинаково везде. –