2014-10-17 2 views
0

Я изо всех сил пытался понять концепцию ошибок округления в Java с плавающей точкой. Хотя я понимаю, что double не предполагается использовать для финансовых расчетов, я не понимаю, почему переменная 'd' не достигает 0.0. Как я могу получить это, чтобы распечатать первый println?Почему числа с плавающей запятой имеют ошибки округления?

package zetcom; 

public class floatingComparison { 
public static void main(String[] args) { 
    double r = Math.sqrt(2); 
    double d = r * r - 2; 

    if (d == 0) 
    { 
     System.out.println("sqrt(2) squared minus 2 is 0"); 
    } 
    else 
    { 
     System.out.println("sqrt(2) squared minus 2 is " + d); 
    } 
    } 
} 

Любое объяснение будет оценено.

+0

Почему бы вам не округлить до 0 десятичных знаков? Я не уверен, что он возвращает, но если вы когда-либо работаете с поплавками, это хорошая идея, чтобы явным образом указать переменной, сколько десятичных знаков вы хотите иметь. Очевидно, что, как утверждают ответы, вы не можете иметь бесконечную точность в конечной системе. – user1274820

+0

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

+0

Обратите внимание, что 'Math.sqrt (x * x)' всегда выдает то же значение, что и 'x' (запрет переполнения или переполнение). Но это теорема. –

ответ

5

Короткий ответ:

Квадратный корень из 2 требует бесконечного количества цифр - то есть, бесконечной точности. double s имеют 52 бита точности. Это много, но это далеко, далеко не бесконечно.

Если вы попытались представить 1/3 с двумя цифрами (0,33), вы не удивились бы ошибкам округления, верно? Вы умножаете его на 3 и не будете удивлены, чтобы получить ответ 0.99 вместо 1.0. Это точно то же самое.

Рытье немного далее ...

Что немного больше не-интуитивным, что числа, которые могут быть представлены с бесконечным числом цифр в базе 10 могуществе не быть в состоянии быть представлена конечное число цифр в базе 2 (что составляет double с и float с). Например, 1/10 составляет 0,1 в базе 10, но это 0,0001100110011 ... в базе 2. Таким образом, он также будет округлен, когда вы храните его как двойное, по той же причине, что и выше: сохранение 1/10 в конечное число цифр в двоичном формате так же невозможно, как хранение 1/3 в конечном числе цифр в десятичной форме.

Копание еще больше ...

И, наконец, вы можете смотреть на него наоборот, слишком. В то время как 1/3 невозможно записать в десятичной форме с конечной точностью, это всего лишь 0,1 в базе 3.

+1

Как в стороне, удваивает точность до 15 знаков после запятой. – Tetramputechture

+0

@Tetramputechture Упс, хороший улов. – yshavit

3

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

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

Смежные вопросы