Могу ли я сохранить точность в Java, если я не сделаю никаких операций с двойником? - PullRequest
0 голосов
/ 27 мая 2020

Я хочу хранить значения от 0,00 до 10,00 в двойном формате. Мне нужна только точность 2 di git. Если я не сделаю никаких операций с двойниками, могу ли я гарантировать, что всегда получу то, что сохранил в переменных?

Я смотрел этот ответ и тестировал этот код:

    double a = 1.2;
    double b = 1.1;
    System.out.println(a - b);
    System.out.println(a);
    System.out.println(b);

Первый отпечаток выводит неточное значение, и объяснение, насколько я понял, состоит в том, насколько неточно машина должна представлять числа. Но почему эти два других отпечатка выводят точные значения? Просто потому, что я не делал никаких операций? Могу ли я предположить, что это всегда будет правдой?

Ответы [ 3 ]

1 голос
/ 27 мая 2020

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

import java.math.*;

public class FloatShow {

    public static void main(String ... args) {

        System.out.println(1.2);

        System.out.println(new Double(1.2).toString());

        System.out.println(new BigDecimal(1.2).toString());
    }
}

Это распечатывает

1.2
1.2
1.1999999999999999555910790149937383830547332763671875

Метод println, заданный двойным, помещает его в коробку и вызывает toString , аналогично Double использует toString, который выполняет округление за вас. BigDecimal использует исходное значение для создания экземпляра и представляет его без очистки. Значит, ваши предположения о точности неверны.

Плавающая точка и фиксированное десятичное число - это две разные концепции. Вот определение арифметики с плавающей запятой c в Википедии :

В вычислениях арифметика с плавающей запятой c (FP) - это арифметика c с использованием формулы c представление действительных чисел в качестве приближения для поддержки компромисса между диапазоном и точностью. По этой причине вычисления с плавающей запятой часто встречаются в системах, которые включают в себя очень маленькие и очень большие действительные числа, требующие быстрой обработки.

Но фиксированная десятичная дробь (например, BigDecimal) отличается, она сохраняет отдельные цифры. BigDecimal медленнее в использовании, но он не делает такого компромисса с точностью до диапазона, как с плавающей запятой. не совсем точны (но точны в пределах известного диапазона ошибок), и можно рассчитать, что скорость стоит компромисса. Для многих бизнес-приложений разница в производительности не является проблемой, потому что узким местом всегда является что-то еще, значения известны точно, а точность не подлежит обсуждению.

1 голос
/ 27 мая 2020

Неточность возникает из-за представления числа как double ( число с плавающей запятой ).

Хотя, как я уже сказал, он использует арифметические c для значений с плавающей запятой. выше, проблема заключается в хранении значений, хотя методы печати часто пытаются скрыть это от нас. Этот ответ должен содержать достаточно подробностей: { ссылка }

Если вы хотите хранить (и оперировать) десятичные числа с точностью до двух десятичных знаков и не более, тогда вам не следует использовать double s (или float s). Вместо этого вам следует работать с точными числами (например, int s или long s). Для двух десятичных знаков вы можете просто использовать 100 == 1.0 или использовать класс BigDecimal.

0 голосов
/ 27 мая 2020

Java использует формат двоичного 32 IEEE-754 для своего типа double. Этот тип имеет свойство, которое для чисел в пределах его диапазона экспоненты, если какое-либо десятичное число из 15 или менее значащих цифр преобразуется в double (с использованием округления до ближайшего, связи с четным), а результирующее число double преобразуется обратно в десятичное число 15-di git, результат равен исходному числу.

Для форматирования чисел с плавающей запятой по умолчанию Java производит ровно столько цифр, чтобы уникально различать guish число в формате с плавающей запятой.

Следствием этих двух свойств является преобразование десятичного числа с 15 или менее значащими цифрами в double с последующим преобразованием этого возврат к десятичным числам с использованием форматирования по умолчанию даст результат, равный исходному числу. В некоторых отношениях он может отличаться. Например, исходная цифра может иметь завершающие нули, которых нет в полученной цифре, например от «3,00» до «3» или от «123,4500» до «123,45».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...