2014-12-28 2 views
4

Сегодня я натолкнулся на своеобразное поведение Math.pow(). Я не могу понять, вывод следующего кода Java:Завершает ли Java Math.pow результат?

long N1 = 999999999999999999L; 
System.out.println("N1 : " + N1); 

long N2 = (long) Math.pow(N1, 1); 
System.out.println("N2 : " + N2); 

я получаю следующий результат:

N1 : 999999999999999999 
N2 : 1000000000000000000 

Я всегда думал, что Math.pow() производит точный результат до тех пор, переданные ему параметры являются целыми или длинными, если нет переполнения (что в данном случае верно).

+9

Этот код является преобразование длинный для двойной и обратно ... что происходит, если вы делаете это преобразование без Math.pow() вообще? Разве это не делает то же самое? –

+0

@MichaelAaronSafyan Вы правы! 'long N3 = (long) (double) N1;' –

+4

'long' и' double' оба занимают 64 бита, и есть очень много значений 'double', которые не могут быть представлены точно с' long'. Поэтому должно быть очень много «длинных» значений, которые не могут быть представлены точно с помощью «double». Вы нашли один из них. –

ответ

10

, потому что он бросает long к double

System.out.println((double)999999999999999999L); 

выходы:

1.0E18 

и

System.out.println((long)(double)999999999999999999L); 

выходы:

1000000000000000000 
+1

+ 1, хотя, поскольку двойники не напечатаны точно, лучше было бы написать 'System.out.println ((long) (double) 999999999999999999L);' – ruakh

+0

спасибо, что помогло мне понять, что происходит за кулисами , – scv

0

Вы можете использовать BigDecimal для таких расчетов и не потерять точность преобразования между типами:

BigDecimal b = new BigDecimal(999999999999999999L); 
BigDecimal pow = b.pow(1);