Числовая точность двойного типа в отладчике Visual C ++ 2008 Express - PullRequest
0 голосов
/ 18 марта 2010

Я использую Visual C ++ 2008 Express Edition и когда я отлаживаю код:

double x = 0.2;

Я вижу в подсказке отладки на 0.20000000000000001

но:

typedef numeric_limits< double > double_limit; 
int a = double_limit::digits10

дает мне: а = 15

Почему результаты в отладчике длиннее обычной точности c ++? На чем основана эта странная точность?

Мой процессор - Intel Core 2 Duo T7100

Ответы [ 3 ]

3 голосов
/ 18 марта 2010
1 голос
/ 18 марта 2010

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

В случае большинства современных машин (включая любые машины, на которых работает MSVC Express), этот формат будет IEEE 754 .

Короче говоря, вот как реальные числа хранятся в IEEE 754: один бит знака, 8 битов экспоненты и 23 бита дроби (для float тип данных - doubles соответственно используют больше битов, но формат та же). Из-за этого вы никогда не сможете достичь идеальной точности и точности. К счастью, вы можете достичь высокой точности и точности практически для любого приложения, включая критические финансовые системы и научные системы.

Вам не нужно знать все, что нужно знать о IEEE754, чтобы использовать плавающие точки в вашем коде. Но есть несколько вещей, которые вы должны знать:

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

double d = 0.2;
double compare = 0.000000001;

double d2 = something;

if( (d - d2 < compare) && (d2 - d < compare) )
{
  // numbers are equal
}

2) Составление ошибок округления. Чем больше раз вы выполняете операции со значением с плавающей запятой, тем больше потеря точности.

3) Вы не можете добавить две плавающие точки совершенно разной величины. Например, вы не можете добавить 1,5x10 ^ 30 и 1,5x10 ^ -30 и ожидать 60 цифр точности.

0 голосов
/ 18 марта 2010

Точное значение, которое дает двойной литерал 0.2, равно 0.200000000000000011102230246251565404236316680908203125.

Большинство функций, которые выводят удваивается после определенного количества десятичных цифр, поэтому вы находитесь в иллюзии, что 0.2 на самом деле дает 0,2

Вот как я получил точное значение:

public static void main(String[] args)
{
    System.out.println(new java.math.BigDecimal(0.2));
}
...