Я работаю над переносом функции sqrt
(для 64-разрядных удвоений) из fdlibm в инструмент проверки модели Я использую в данный момент (cbmc).
В рамках моих работ я много читал о стандарте ieee-754, но, думаю, я не понял гарантии точности для основных операций (включая sqrt).
Тестирование моего порта fdlibm sqrt, я получил следующий расчет с sqrt в 64-битном двойном:
sqrt(1977061516825203605555216616167125005658976571589721139027150498657494589171970335387417823661417383745964289845929120708819092392090053015474001800648403714048.0) = 44464159913633855548904943164666890000299422761159637702558734139742800916250624.0
(этот случай нарушил простое пост-условие в моем тесте относительно точности, я не уверен, если это пост-условие возможно с IEEE-754)
Для сравнения несколько инструментов с несколькими точками вычисляли что-то вроде:
sqrt(1977061516825203605555216616167125005658976571589721139027150498657494589171970335387417823661417383745964289845929120708819092392090053015474001800648403714048.0) =44464159913633852501611468455197640079591886932526256694498106717014555047373210.truncated
Можно видеть, что 17-е число слева отличается, что означает ошибку, например:
3047293474709469249920707535828633381008060627422728245868877413.0
Вопрос 1: разрешено ли это огромное количество ошибок?
В стандарте говорится, что каждая базовая операция (+, -, *,/, sqrt) должна быть в пределах 0,5 ulps, что означает, что она должна быть равна математически точному результату, округленному до ближайшего fp-представления (wiki говорит что в некоторых библиотеках только 1 ulp, но это не так важно на данный момент).
Вопрос 2: Означает ли это, что каждая базовая операция должна иметь ошибку < 2.220446e-16 с 64-битным удвоением (машинный-эпсилон)?
Я подсчитал то же самое с Linux-системой x86-32 (glibc/eglibc) и получил тот же результат, что и с fdlibm, что позволяет мне думать, что:
- a: Я сделал что-то неправильно (но как:
printf
был кандидатом, но я не знаю, может ли это быть причиной). - b: ошибка/точность распространена в этих библиотеках.