2011-01-25 1 views
0

Я работаю с Math.pow() функцией, и имею следующий код:Ява Math.pow() Эта функция возвращает запутанные результаты

double monthlyRate = (0.7d/12); 
int loanLength = 3; 

double powerTest = Math.pow(1.00583, 36); 
double powerResult = Math.pow((1 + monthlyRate),(loanLength * 12)); 

Когда запускаются через отладчик, значения становятся

powerTest => 1.2327785029794363 
powerResult => 7.698552870922063 

Первый правильный. Я перешел в функцию Math.pow на обеих линиях назначения. Для powerTest, параметры для Math.pow являются двойной а => 1,00583 двойной б => 36,0

Для powerResult, они двойной а => +1,0058333333333333 двойной б => 36,0

Я знаю, что это проблема с тем, как машина с плавающей запятой выполняется машиной, я просто не знаю, как ее исправить. Я пытался делать следующее перед расчетом с плохими результатами:

monthlyRate = Math.round(monthlyRate * 1000)/1000; 
+0

Что вы ожидаете от (1+ (0.7/12))^(3⋅12)? Я получаю 7.6985528709220588862786 в обычном калькуляторе. –

+0

На Java вы должны использовать BigDecimal для выполнения денежных операций. Проверьте мой ответ. – vz0

ответ

9

1 + monthlyRate является 1.0583..., а не 1.00583.

+0

Не могу поверить, что я смотрел на это в течение 30 минут и пропустил эту опечатку. Спасибо за помощь. –

1
Math.round(monthlyRate * 1000)/1000.0; 

Вы использовали целочисленное деление.

+0

Игнорируйте это, фактическая проблема - дополнительный ноль, как указано ** axtavt **. Я оставляю ответ, если OP действительно хочет выполнить округление. –

+0

Спасибо, Никита, заметьте, что если мне нужно написать аналогичную функцию в будущем –

2

Я думаю, что часть проблемы в том, что 0.7/12 ~ 0.058333 и 1.0583 > 1.00583. Моя ставка заключается в том, что это истинный источник вашего несоответствия, корректировки с плавающей запятой имеют мало общего с этим.

3

Ваше выражение 0.7d/12 = 0.0583, в выражении powerTest вы используете 0.00583.

1

На Java вы можете использовать BigDecimal для выполнения денежных операций в результате точных номеров: это Sun/Oracle recommended way, чтобы хранить денежные суммы.

// I'm using Strings for most accuracy 

BigDecimal monthlyRate = new BigDecimal("0.7").divide(new BigDecimal(12)); 
int loanLength = 3; 

BigDecimal powerTest = new BigDecimal("1.00583").pow(36); 
BigDecimal powerResult = BigDecimal.ONE.add(monthlyRate).pow(loanLength * 12); 
+1

Пожалуйста, объясните ваши downvotes. ОП выполняет денежные операции, он * должен * использовать BigDecimal. – vz0

2

Очевидно, что такая большая разница в resut (1,23 ... и 7,70) не связано с тем, как поплавки закодированы, но больше, чем вы сделали ошибку где-то 1 + 0,7/12 = 1,0583 отличается от 1.00583 ;-).