Ошибка анализа в где. Haskell [дубликат]

Математическая математика с плавающей запятой такова. В большинстве языков программирования он основан на стандарте IEEE 754 . JavaScript использует 64-битное представление с плавающей запятой, которое совпадает с Java double. Суть проблемы состоит в том, что числа представлены в этом формате как целое число раз в два раза; рациональные числа (такие как 0.1, который является 1/10), знаменатель которого не является степенью двух, не могут быть точно представлены.

Для 0.1 в стандартном формате binary64 представление может записывается в точности как

  • 0.1000000000000000055511151231257827021181583404541015625 в десятичной форме или
  • 0x1.999999999999ap-4 в нотации C99 hexfloat .

Напротив, рациональное число 0.1, которое является 1/10, может быть записано точно как

  • 0.1 в десятичной форме или
  • 0x1.99999999999999...p-4 в аналоге обозначения гексафлоата C99, где ... представляет собой бесконечную последовательность 9.

Константы 0.2 и 0.3 в вашей программе также будут приближенными к их истинные ценности. Бывает, что ближайший double до 0.2 больше, чем рациональное число 0.2, но ближайший double до 0.3 меньше, чем рациональное число 0.3. Сумма 0.1 и 0.2 заканчивается выше, чем рациональное число 0.3 и, следовательно, не согласуется с константой в вашем коде.

Достаточно полное рассмотрение арифметических вопросов с плавающей запятой Что каждый компьютерный ученый должен знать о арифметике с плавающей точкой . Для более простого объяснения см. floating-point-gui.de .

18
задан Zeta 7 March 2016 в 23:14
поделиться

1 ответ

Проблема двоякая. Прежде всего, Haskell чувствителен к отступу, например. следующий код недействителен:

example = (a, b)
  where
    a = "Hello"
     b = "World"

Обе привязки должны иметь отступы с одинаковым количеством пробелов / вкладок (см. правило off-side ). Хотя это очевидно в этом случае, оно довольно скрыто в следующем, где я обозначаю пробел · и вкладку »:

example = (a, b)
··where
····a = "Hello"
»   b = "World"

Это будет выглядеть как действительный код Haskell, если редактор отобразит вкладки, выровненные по кратным на четыре. Но это не так. Вкладки Haskell выровнены по кратным восьми, поэтому код будет интерпретироваться так:

example = (a, b)
··where
····a = "Hello"
»       b = "World"

Во-вторых, если вы используете только вкладки, вы можете получить макет, который выглядит неправильно. Например, следующий код выглядит корректно, если вкладка отображается с шестью или более пробелами (в этом случае восемь):

example = (a, b)
»       where»  a = "Hello"
»       »       b = "World"

Но в другом редакторе, который использует 4 пробела, он больше не будет выглядеть :

example = (a, b)
»   where»  a = "Hello"
»   »   b = "World"

Это все еще правильно. Тем не менее, кто-то, кто привык к пробелам, может переписывать b 'связывание с пробелами и заканчивать с ошибкой парсера.

Если вы применяете кодовое соглашение во всем своем коде, что гарантирует, что вы используете только вкладки на начале строки и использовать новую строку после where, let или do, вы можете избежать некоторых проблем (см. 11 ). Однако текущие релизы GHC предупреждают о вкладках по умолчанию , потому что они имеют [ a источник из многих ошибок парсера в прошлом, поэтому вы, вероятно, захотите также избавиться от них.

См. также

22
ответ дан Zeta 26 August 2018 в 05:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: