Двойники и арифметика - PullRequest
       26

Двойники и арифметика

2 голосов
/ 11 марта 2012

Я компилирую и запускаю этот код с MSVC2008

long double x = 111111111;
long double y = 222222222;
long double Z = x * y;

cout << z << endl;

Когда я отлаживаю, z равно

24691357975308640

Математически z должно быть

24691357975308642

Что происходит?

Ответы [ 4 ]

7 голосов
/ 11 марта 2012

Двойные числа точны только до 16 цифр .Если я посчитал правильно, то у вас есть 17 цифр, а правильные до 16. Если вы хотите заниматься этим видом математики и будете иметь только целые числа, используйте целые числа.Для такого большого числа вам нужно будет использовать uint64_t.

4 голосов
/ 11 марта 2012

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

Например, для числа с плавающей запятой 1 + 11 + (1) +52 ( см. Здесь ) у нас есть 53 бита точности, что дает нам 53 & times; log 10 2 цифры точности, то есть 15. Таким образом, мы печатаем только 15 цифр:

#include <iomanip>
#include <iostream>

std::cout << std::setfill('0') << std::setprecision(15) << std::scientific
          << Z << std::endl;

Результат:

2.469135797530864e+16

Теперь мы сделали манифест точности, и результат действительно верен с такой точностью.

Если вам не нравится магия 15 в коде, вы должны #include <limits> и использовать:

std::numeric_limits<decltype(Z)>::digits10
1 голос
/ 11 марта 2012

Как правило, на ваш вопрос можно написать книгу.Короче говоря, продолжается арифметика с плавающей точкой.См. Плавающая точка .Кроме того, преобразование двойных значений в ASCII (для отображения) также сложно и не точно.Вы также можете посмотреть на арифметику произвольной точности .

1 голос
/ 11 марта 2012

Арифметика с плавающей точкой продолжается. Это - хорошее чтение. В основном, на компьютерах могут возникать проблемы с хранением и обработкой чисел с плавающей запятой, поэтому вы получаете такие арифметические ошибки.

...