Отформатируйте двойное число без потери точности, но с минимальным количеством цифр.C++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Отформатируйте двойное число без потери точности, но с минимальным количеством цифр.

Сообщение Anonymous »

В нашей кодовой базе C++ у нас есть метод форматирования по умолчанию для преобразования двойных чисел с плавающей запятой в строки, который используется, в частности, для сериализации JSON и для журналов отладки. Для этого форматирования чисел по умолчанию у меня есть следующие противоречивые требования:
  • Удобство чтения человеком. Предпочитайте от 1000 до 1e3 или от 0,125 до 1,25e-1.
  • Сохраняйте точность. Предпочитайте от 3.1415926535897931 до 3.14.
  • Избегайте использования ложных цифр в десятичных числах. Предпочитайте от 0,1 до 0,10000000000000001.
До сих пор лучший компромисс, который я нашел, — это использовать эквивалент форматирования printf("%.15g", value). Он соответствует требованиям 1 и 3, но не полностью 2. Потеря точности составляет около 4 бит.
Другие люди используют форматирование по умолчанию на основе "%.17g", которое соответствует требованиям 1 и 2, но не 3. Число 0,2, например, отформатировано как 0,20000000000000001.
Между этим формат "%.16g" близок к выполнению требований 2 и 3, но не всегда для обоих.
В качестве иллюстрации я желаю 0,3 будет отформатировано как 0,3, а 0,1+0,2, которое немного больше из-за ошибок округления, будет отформатировано как 0,30000000000000004, чтобы увидеть разницу.
Я написал следующую функцию, которая форматирует числа с плавающей запятой так, как я хочу, в качестве доказательства концепции. Однако это неприемлемо с точки зрения производительности, поскольку оно может выполнять до 34 преобразований между двойными и строками, что дает ограниченный прирост точности по сравнению с текущей реализацией с "%.15g".

Код: Выделить всё

std::string doubleToString(double number)
{
char buffer[32];
long long intVal = static_cast(number);
if(intVal == number)
{
sprintf(buffer, "%lld", intVal);
}
else
{
for(int i=1; i>> 0.3
0.3
>>> 0.1+0.2
0.30000000000000004
>>>
Есть ли способ добиться такого же поведения в C++, не жертвуя при этом слишком большой производительностью?

Подробнее здесь: https://stackoverflow.com/questions/658 ... -of-digits
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»