Я пытаюсь написать функцию на языке программирования D, чтобы заменить вызовы strtold. (Обоснование: чтобы использовать strtold из D, необходимо преобразовать строки D в строки C, что неэффективно. Кроме того, strtold не может быть выполнен во время компиляции.) Я пришел к реализации, которая в основном работает, но я кажется, теряют некоторую точность в наименее значимых битах.
Код интересующей части алгоритма приведен ниже, и я вижу, откуда берется потеря точности, но я не знаю, как от нее избавиться. (Я пропустил много частей кода, которые не относились к основному алгоритму, чтобы спасти людей, читающих.) Какой алгоритм «строка-в-число» гарантирует, что результат будет максимально приближен к числу IEEE строка значения, представленного строкой.
real currentPlace = 10.0L ^^ (pointPos - ePos + 1 + expon);
real ans = 0;
for(int index = ePos - 1; index > -1; index--) {
if(str[index] == '.') {
continue;
}
if(str[index] < '0' || str[index] > '9') {
err();
}
auto digit = cast(int) str[index] - cast(int) '0';
ans += digit * currentPlace;
currentPlace *= 10;
}
return ans * sign;
Кроме того, я использую юнит-тесты для старой версии, которые делали что-то вроде:
assert(to!(real)("0.456") == 0.456L);
Возможно ли, что ответы, выдаваемые моей функцией, на самом деле более точны, чем представление, которое компилятор создает при разборе литерала с плавающей запятой, но компилятор (который написан на C ++) всегда точно соответствует strtold, потому что он использует strtold внутренне для разбора литералов с плавающей точкой?