http://www.learncpp.com/cpp-tutorial/25-floating-point-numbers/ я был об этом в последнее время для рассмотрения C++.
В общем вычислительном классе преподаватели склонны не покрывать эти мелочи, хотя мы знали то, что означали погрешности округления.
Кто-то может помочь мне с тем, как избежать погрешности округления?
Учебное руководство показывает пример кода
#include
int main()
{
using namespace std;
cout << setprecision(17);
double dValue = 0.1;
cout << dValue << endl;
}
Это производит
0.10000000000000001
Плаванием по умолчанию сохранен 6 цифрами точности. Поэтому, когда мы переопределяем значение по умолчанию, и просит больше (n этот случай, 17!!), мы можем встретиться с усечением (как объяснено учебным руководством также). Для двойного самое высокое равняется 16.
В целом, как хорошие программисты на C++ избегают погрешности округления? Вы парни всегда смотрят на двоичное представление числа?
Спасибо.
Канонический совет по этой теме - прочитать «Что должен знать каждый компьютерный ученый об арифметике с плавающей запятой» Дэвида Голдберга.
Краткая версия - вы действительно не можете избежать округления и других ошибок представления, когда пытаетесь представить числа с основанием 10 в базе 2 (т. Е. Используя число с плавающей запятой или двойное значение для представления десятичного числа номер). Вам в значительной степени нужно либо определить, сколько у вас действительно значащих цифр, либо вам нужно переключиться на (более медленную) библиотеку произвольной точности.
Другими словами, чтобы минимизировать ошибки округления, может быть полезно сохранять числа в десятичной фиксированной точке (и фактически работать с целыми числами).
#include <iostream>
#include <iomanip>
int main() {
using namespace std;
cout << setprecision(17);
double v1=1, v1D=10;
cout << v1/v1D << endl; // 0.10000000000000001
double v2=3, v2D=1000; //0.0030000000000000001
cout << v2/v2D << endl;
// v1/v1D + v2/v2D = (v1*v2D+v2*v1D)/(v1D*v2D)
cout << (v1*v2D+v2*v1D)/(v1D*v2D) << endl; // 0.10299999999999999
}
Большинство подпрограмм вывода с плавающей запятой проверяют, очень ли близок ответ к тому, чтобы быть представленным в базе 10, и округляют ответ, чтобы фактически быть четным при выводе. Устанавливая точность таким образом, вы замыкаете этот процесс.
Это округление сделано потому, что почти ни один ответ, который выходит даже в базе 10, не будет четным (т.е. оканчивается бесконечной цепочкой завершающих нулей) в базе 2, которая является базой, в которой число представлено внутри. Но, конечно, общая цель процедуры вывода состоит в том, чтобы представить числа в удобной для человека форме, и большинство людей в мире сегодня читают числа с основанием 10.