|
|
Опубліковано 07.04.2015 14:53:05
|
|
|

Класи операцій для великих чисел надаються в Java, а саме клас java.math.BinInteger та клас java.math.BigDecimal. Ці два класи використовуються для високоточних обчислень: клас BigInteger — це клас обробки великих цілих чисел, а клас BigDecimal — для великих і малих чисел. Нижче ми представляємо клас BigDecimal: Реалізація BigDecimal використовує переваги BigInteg, але додає концепцію десяткових чисел. Загальні дані float і double type можна використовувати лише для наукових або інженерних розрахунків, оскільки в комерційних обчисленнях необхідна чисельна точність відносно висока, тому використовується клас java.math.BigDecimal, який підтримує будь-яку точність фіксованих точок і може бути використаний для точного розрахунку валютних значень. Нижче ми коротко представимо його використання з прикладами
java.math.BigDecimal
Сьогодні я написав програму про бінарне та десяткове перетворення з посиланням на підручник, і алгоритм програми не є складним, але після написання я зрозумів, що незалежно від того, чи це 2 до 10, чи 10 до 2, це не є хорошим перетворенням для чисел більших за 2,1 мільярда, тобто більше за цілочисельний діапазон. стане 0. Довідкові книги виявили, що використання BigInteger вирішує цю проблему. Тож я знайшов JDK, потім кілька разів тестував його і нарешті успішно написав! Досвід використання виглядає так:
1. BigInteger належить java.math.BigInteger, тому імпортуйте цей клас перед кожним використанням. Іноді я забував імпортувати на початку, тому запит не з'являється у постійному запиті.
2. Існує багато методів будівництва, але тепер їх іноді використовують: BigInteger(String val) Перетворити десяткове рядкове представлення BigInteger у BigInteger. BigInteger(String val, int radix) Перетворює рядкове представлення BigInteger для заданої потужності у BigInteger. Щоб перетворити 2 int типу у BigInteger тип, запишемо BigInteger two=нове BigInteg("2"); Примітка 2: подвійні лапки не можна пропускати
3. Клас BigInteger імітує всі int-тип математичні операції, такі як add()=="+", divide()=="-" тощо, але зверніть увагу, що його вміст не може безпосередньо використовуватися для математичних операцій при виконанні математичних операцій і повинен застосовувати внутрішні методи. І його операнд також має бути типу BigInteg. Наприклад: two.add(2) є неправильною операцією, оскільки 2 не стає типом BigInteger.
4. Коли ви хочете вивести результати розрахунку, слід використовувати метод .toString, щоб перетворити його у десятковий рядок, як описано нижче: String toString() Повертає десяткове рядкове представлення цього BigInteg. Метод виводу: System.out.print(two.toString());
5. Поясніть три використані функції. BigInteger remainder(BigInteger val) Повертає BigWholeeger зі значенням (цей % val). BigInteger negate() BigInteger повертає значення (-this). int compareTo(BigInteger val) Порівняйте це BigInteger із зазначеним BigInteger. Remainderis використовується для пошуку решти. Negate перетворює операнд на протилежність. Порівняння детально пояснюється наступним чином: порівнятиЗ
public int compareTo(BigInteger val)
Порівняйте це BigInteger із зазначеним BigInteger. Цей метод переважає для кожного з шести булевих операторів порівняння (<, ==, >, >=, !=, <=). Запропоноване твердження для виконання цих порівнянь: (x.compareTo(y) <op> 0), де — <op> один із шести операторів порівняння.
Специфікатор: <BigInteger> інтерфейс Порівнянний
Параметри: val — BigInteger, який порівнює цей BigInteger з ним. Назад:
Заголовок: Реалізація точних розрахунків чисел з плаваючою комою в Java AYellow (Оригінальна) модифікація Ключові слова: Java, точний розрахунок з плаваючою комою.
Питання: Що б ми побачили, якби скомпілювали і запускали таку програму? Тест публічного класу{ public static void main(String args[]){ System.out.println(0.05+0.01); System.out.println(1.0-0.42); System.out.println(4.015*100); System.out.println(123.3/100); } };
Ви правильно прочитали! Результат, справді, є 0.060000000000000005 0.5800000000000001 401.49999999999994 1.2329999999999999
Прості float і double типи в Java не можуть працювати. Ця проблема зустрічається не лише в Java, а й у багатьох інших мовах програмування. У більшості випадків розрахунки точні, але можна спробувати ще кілька разів (можна зробити цикл), щоб спробувати помилки, як описана вище. Тепер я нарешті розумію, чому існує код BCD. Ця проблема досить серйозна: якщо у вас є 9,999999999999999999 юанів, ваш комп'ютер не подумає, що ви можете купити товар за 10 юанів. Деякі мови програмування пропонують спеціалізовані типи валют для вирішення цієї ситуації, але Java цього не робить. Тепер подивимось, як це виправити.
Округлення Наша перша реакція — робити округлення. Круглий метод у класі математики не можна встановити так, щоб тримати кілька десяткових знаків, ми можемо зробити лише так (залишити два знаки): Публічний подвійний раунд(подвійне значення){ повернути Math.round(value*100)/100.0; }
На жаль, наведений вище код не працює, передача 4.015 у цей метод поверне 4.01 замість 4.02, як ми бачили вище 4.015*100=401.49999999999999 Тому, якщо ми хочемо точно округлювати операції, ми не можемо використовувати прості типи для виконання операцій java.text.DecimalFormat також не вирішує цю проблему: System.out.println(new java.text.DecimalFormat("0.00").format(4.025)); Вихід — 4.02
BigDecimal Цей принцип також згадується в книзі «Ефективна Java»: float і double можна використовувати лише для наукових або інженерних обчислень, а в бізнес-обчисленнях потрібно використовувати java.math.BigDecimal. Існує 4 способи побудови BigDecimal, нам байдуже до двох, які зроблені з BigIntenumer, тому є ще два, а саме: BigDecimal (подвійний val) Перекладає подвійний у BigDecimal. BigDecimal (String val) Перекладає репрезентацію String BigDecimal у BigDecimal у BigDecimal.
API коротко описаний і зазвичай простіший у використанні. Ми можемо використати його, навіть не замислюючись, у чому проблема? Коли щось пішло не так, я дізнався, що в детальному описі є такий абзац, який із вищезазначених методів є достатнім: Примітка: результати цього конструктора можуть бути дещо непередбачуваними. Можна припустити, що новий BigDecimal(.1) точно дорівнює .1, але насправді він дорівнює .1000000000000000055511151231257827021181583404541015625. Це так тому, що 0,1 не можна точно представити як подвійний (або, власне, як двійкову частку будь-якої скінченної довжини). Отже, довге значення, яке передається конструктору, не є точно рівним 0,1, незважаючи на зовнішність. Конструктор (String) натомість цілком передбачуваний: новий BigDecimal («.1») точно дорівнює .1, як і слід було очікувати. Тому зазвичай рекомендується використовувати конструктор (String) замість цього.
Виявляється, якщо потрібно точно обчислювати, потрібно використовувати String для створення BigDecimal! Приклад у книзі Effective Java використовує String для створення BigDecimal, але в книзі це не підкреслюється, що може бути невеликою помилкою.
Розв'язок Тепер, коли ми вирішили цю проблему, принцип полягає в тому, щоб використовувати BigDecimal і обов'язково використовувати String. Але уявіть, що якщо ми хочемо виконати операцію додавання, спочатку потрібно перетворити два числа з плаваючою комою у String, потім створити BigDecimal, викликати метод додавання на одному з них, передати інший як аргумент, а потім перетворити результат операції (BigDecimal) у число з плаваючою комою. Чи зможеш ти витримати такий виснажливий процес? Нижче наведено клас інструментів Arith для спрощення операції. Вона пропонує такі статичні методи, включаючи додавання, віднімання, множення та ділення, а також округлення: Публічне статичне подвійне додавання (Double V1, Double V2) Публічний статичний подвійний сабвуфер (подвійний V1, подвійний V2) Публічний статичний подвійний модуль (подвійний V1, подвійний v2) Публічний статичний подвійний див (подвійний v1, подвійний v2) Публічний статичний подвійний див (подвійний v1, подвійний v2, інтелектуальна шкала) Публічний статичний подвійний раунд (подвійний V, INT)
Додаток
Вихідний файл Arith.java:
імпорт java.math.BigDecimal; /** * Оскільки прості типи Java не можуть точно виконувати операції з плаваючою комою, цей клас інструменту забезпечує дрібні * Точні операції з плаваючою комою, включаючи додавання, віднімання, множення, ділення та округлення. */
публічний клас Arith{
Стандартна точність операцій ділення приватний статичний фінальний int DEF_DIV_SCALE = 10;
Цей клас не можна інстанціювати private Arith(){ }
/** * Забезпечує точні операції додавання. * @param v1 додано * @param додавання у v2 * @return Сума двох параметрів */
Публічне статичне подвійне додавання(подвійне v1,подвійне v2){ BigDecimal b1 = новий BigDecimal(Double.toString(v1)); BigDecimal b2 = новий BigDecimal(Double.toString(v2)); повернути b1.add(b2).doubleValue(); }
/** * Забезпечує точні операції віднімання. * @param v1 віднімається * @param v2 мінус * @return Різниця між двома параметрами */
Публічний статичний подвійний саб (Double V1,Double V2){ BigDecimal b1 = новий BigDecimal(Double.toString(v1)); BigDecimal b2 = новий BigDecimal(Double.toString(v2)); повернути b1.subance(b2).doubleValue(); }
/** * Забезпечує точні операції множення. * @param v1 множиться * @param множник v2 * @return Добуток двох параметрів */
Публічний статичний подвійний mul(double v1,double v2){ BigDecimal b1 = новий BigDecimal(Double.toString(v1)); BigDecimal b2 = новий BigDecimal(Double.toString(v2)); повернути b1.multiply(b2).doubleValue(); }
/** * Забезпечує (відносно) точні операції поділу, коли відбувається невичерпне ділення * 10 десяткових знаків і наступні цифри округлені. * @param v1 поділяється * @param v2 divisor * @return Фактор двох параметрів */
Публічний статичний подвійний div(double v1,double v2){ return div(v1,v2,DEF_DIV_SCALE); }
/** * Забезпечує (відносно) точні операції з розподілом. Коли виникає невичерпна ситуація, її вказує параметр масштабу * Визначте точність, і числа після неї будуть округлені. * @param v1 поділяється * @param v2 divisor * @param шкала означає, що вона має бути точною до кількох десяткових знаків. * @return Фактор двох параметрів */
Публічний статичний подвійний DIV(подвійний v1, подвійний v2,інтелект шкала){ if(scale<0){ додай новий IllegalArgumentException( «Шкала має бути додатним цілим або нуль»); } BigDecimal b1 = новий BigDecimal(Double.toString(v1)); BigDecimal b2 = новий BigDecimal(Double.toString(v2)); return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue(); }
/** * Забезпечує точне закруглення десяткових. * @param v вимагає округлення чисел * @param шкала резервується після десяткової крапки * @return Округлені результати */
Публічний статичний подвійний раунд(подвійний v,інтеграційний масштаб){ if(scale<0){ додай новий IllegalArgumentException( «Шкала має бути додатним цілим або нуль»); } BigDecimal b = новий BigDecimal(Double.toString(v)); BigDecimal one = новий BigDecimal("1"); return b.divide(one, scale,BigDecimal.ROUND_HALF_UP).doubleValue(); } }; |
Попередній:Краще не ставити рядок із значенням як первинним ключемНаступний:JDK, JRE, JVM відмінності та зв'язки
|