Почему раунд неверен в CCL?

Изучаю Common Lisp 2 месяца, встречаю головоломку, вот код:

CL-USER> (round 33.6)
34
-0.40000153

кто-нибудь объяснит? Спасибо


person Hercules Shek    schedule 06.03.2014    source источник


Ответы (1)


Я не уверен, что понимаю вашу проблему. В CLisp round округляется до ближайшего целого числа (если вы не укажете делитель). Ближайшее целое число к 33.6 равно 34, так что этот бит правильный.

А поскольку round возвращает и частное и остаток, он дает 34 с остатком -0.4. Этот бит в основном правильный, поэтому я подозреваю, что вам интересно, почему это только "в основном".

Причина, по которой это не точно -0.4, почти наверняка связана с ограниченной точностью чисел с плавающей запятой. Результат вычисления разницы между (кажущимся точным) числом с плавающей запятой и целым числом может удивить:

CL-USER> (- 23.6 24) -0.39999962

Вы ожидаете, что в идеальном мире это вернет -0.4, но это не так по причинам, упомянутым выше.

Если вы хотите узнать, почему это так (т. е. как работают операции с плавающей запятой), вы можете проверить это и это в качестве примера.

person paxdiablo    schedule 06.03.2014
comment
Я хочу знать низкоуровневые данные - person Hercules Shek; 06.03.2014
comment
вычисление между 2 числами с плавающей запятой: CL-USER› (+ 25.2 2.2) 27.400002 - person Hercules Shek; 06.03.2014
comment
@ Геркулес, я обновил ответ, чтобы указать вам на другие вопросы о слабостях с плавающей запятой. - person paxdiablo; 06.03.2014
comment
Спасибо! хотя я не сделал понятной низкоуровневую реализацию CCL, я понял, как хранится float. - person Hercules Shek; 06.03.2014
comment
@HerculesShek, вы можете использовать disassemble в LISP, чтобы действительно разобраться в том, что происходит с арифметической операцией, но вы обнаружите, что на этом уровне он не сильно отличается от любого другого языка, и вы действительно имеете дело с общей точностью с плавающей запятой вопросы. - person lurker; 06.03.2014