#math #lisp #floating-point #precision
#математика #lisp #значение с плавающей запятой #точность
Вопрос:
Что пошло не так?
[1]> (log (exp 1))
0.99999994
Комментарии:
1. Добро пожаловать в мир чисел с плавающей запятой. Посмотрите на столбец «связанные» в правой части этой страницы для многих, очень многих объяснений.
Ответ №1:
Это связано с конечной точностью представлений дробных чисел с плавающей запятой.
Пожалуйста, смотрите: http://en.wikipedia.org/wiki/Floating_point
(exp 1)
будет приближением e
(что требует бесконечной точности для идеального представления). Натуральный логарифм этого приближения будет приблизительно (но не точно) 1
. Понимание представления с плавающей запятой позволит вам понять, почему это происходит.
CLISP использует собственное представление чисел с плавающей точкой в вашей машинной архитектуре. Чаще всего это представление выполняется в одном из форматов, указанных в IEEE 754 (обычно 32- или 64-разрядном; в вашем случае это выглядит как 32-разрядный). В двух словах, дробные части представлены суммой обратных степеней 2 (т. е. некоторой комбинацией 1/2
, 1/4
, 1/8
, … 1/2^32
, и т.д.)
Ответ №2:
Попробуйте использовать двойную точность с плавающей запятой:
(log (exp 1.0d0))
=> 1.0D0
; по крайней мере, в Clozure CL
Комментарии:
1. При любой конечной точности с плавающей запятой будут проблемы с округлением. Если вы получаете «правильный» результат, есть два вероятных объяснения. Первое — вам повезло с округлением, но вы получите ошибку для (log (exp 1.5d0)) или какого-либо другого числа. Во-вторых, для целей отображения применяется десятичное округление, которое дает удачный результат, но выдаст ошибку для другого начального значения. Маловероятной возможностью является символьная математика, полностью исключающая числовое вычисление. Это редко встречается за пределами языков, встроенных в несколько специализированных приложений.