2010-03-18 2 views
0

Я использую Visual C++ 2008 Express Edition и когда я отладка коды:Численной точность двойного типа в Visual C++ 2008 Express отладчик

double x = 0.2; 

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

но:

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

дает мне: а = 15

Почему результаты в отладчик больше т han normal C++ precision? В чем заключается эта странная точность?

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

+6

Добро пожаловать с плавающей точкой. – GManNickG

+1

Этот вопрос (или варианты) возникает через несколько дней здесь. Определенно дубликат какого-то рода! – spender

ответ

1

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

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

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

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

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

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

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

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

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

public static void main(String[] args) 
{ 
    System.out.println(new java.math.BigDecimal(0.2)); 
} 
Смежные вопросы