Можлива помилка переповнення Java BigDecimal


78

Я тестував граничні умови на якомусь коді, що включає a BigDecimal, і я помітив, що коли a BigDecimalініціалізується за допомогою String, "1e2147483647"він поводиться несподівано. Здається, воно має значення між 0і 1e-2147483647. Коли я намагаюся зателефонувати intValue(), я отримую NegativeArraySizeException. Слід зазначити, що 2147483647це максимальне значення цілого числа в моїй системі. Я роблю щось не так, чи це проблема BigDecimal?

BigDecimal test = new BigDecimal("1e2147483647");

test.compareTo(new BigDecimal(0));  //Returns 1
test.compareTo(new BigDecimal("1e-2147483647"));  //Returns -1
test.intValue();  //Throws NegativeArraySizeException


Дякую, я не бачив цього запитання. Я був просто здивований, що це не викинуло NumberFormatException з конструктора, як це робиться для цифри на одну цифру більше.
DJMatch3000

Це більше пропозиція, ніж знання, але 1e-2147483647це досить велика кількість. Якщо бути точним, log_2(10^2147483647) / 8 / 1024^3 = 0.83...слід дати мінімальний розмір (у гігабайтах), щоб представляти таке велике число, як ціле число. Можливо, це якась проблема з алокатином пам'яті?
Turing85

3
@ DJMatch3000: Ні, ваші дані правильні та репрезентативні, хоча це максимальний показник, який ви можете представити BigDecimal. Ваша помилка є законною.
Louis Wasserman

Відповіді:


87

Ні, у вас, здається, законна помилка. Помилка присутня в JDK7, але виправлена ​​в JDK8. Ваші значення правильно відображаються як BigDecimals, і вони повинні поводитися правильно, але не слід.

Трасування через вихідний кодBigDecimal , у рядку 2585, this.precision()дорівнює 1 і this.scaleє -2147483647. this.precision() - this.scaleтому переповнення, і наступне переповнення обробляється неправильно.

Ця помилка була виправлена в JDK8 шляхом віднімання в longарифметиці .


Це в Java 17 на Android 17 (подібно до JDK6)?
Бен Ледж'єро
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.