Компьютерный справочник
4 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд

Double compare java

Correct way to compare floats or doubles in Java

By Lokesh Gupta | Filed Under: Java Basics

Correctly compare float or compare double is not only Java specific problem. It can be observed in almost all the programming languages today. In computer memory, floats and doubles are stored using IEEE 754 standard format. How the actual storage and conversion works, it is out of scope of this article.

For now, just understand that during computations and conversions, minor rounding errors can be introduced in these numbers. That’s why it is not advisable to simply rely on the equality operators (==) to compare floating-point numbers.

Let’s learn how to compare float values in Java.

1. Compare double – Simple comparison [Not recommended]

First look at the simple comparison to understand what exactly is wrong with comparing double with == operator. In given program, I am creating same floating point number (i.e. 1.1 ) using two methods:

  1. Add .1 , 11 times.
  2. Multiply .1 to 11.

In theory, both operations should produce the number 1.1 . And when we compare the results of both methods, it should match.

Look at the both values printed in console. f1 is computed to 1.0999999999999999 . Its exactly the problem which rounding off causes internally. That’s why, floating point comparison with ‘==’ operator is not recommended.

2. Compare double – Threshold based comparison [Recommended]

Now when we know the problem with equality operator, lets solve it. Using programming, we cannot change the way these floating point numbers are stored or computed. So we have to adapt a solution where we agree that a determine the differences in both values which we can tolerate and still consider the numbers equal. This agreed upon difference in values is called the threshold or epsilon.

So now to use ‘threshold based floating point comparison‘, we can use the Math.abs() method to compute a difference between the two numbers and compare the difference to a threshold value.

3. Compare double – Compare with BigDecimal [Recommended]

In BigDecimal class, you can specify the rounding mode and exact precision which you want to use. Using the exact precision limit, rounding errors are mostly solved.

Best part is that BigDecimal numbers are immutable i.e. if you create a BigDecimal BD with value «1.23» , that object will remain «1.23» and can never be changed. This class provide many methods which can be used to do numerical operations on it’s value.

You can use it’s compareTo() method to compare to BigDecimal numbers. It ignore the scale while comparing.


Java program to compare double with BigDecimal class.

Now just to verify, let’s solve out original problem using BigDecimal class.

That’s all about comparing floating point numbers in java. Share your thoughts in comments section.

compare « double « Java Data Type Q&A

1. Java double comparison epsilon stackoverflow.com

I wrote a class that tests for equality, less than, and greater than with two doubles in Java. My general case is comparing price that can have an accuracy of .

2. Java: Double Value Comparison stackoverflow.com

Do we need to be careful when comparing a double value against zero?

3. Why is Java’s Double.compare(double, double) implemented the way it is? stackoverflow.com

I was looking at the implementation of compare(double, double) in the Java standard library (6). It reads: My question is, what should be an epsilon value? Is there any robust .

5. why do comparison of Double references return false? stackoverflow.com

Why String return true but Double return false ? I have .

6. Comparing doubles in Java gives odd results stackoverflow.com

I really can’get my head around why the following happens: This however works as expected: in Java?

8. Comparing two numbers stackoverflow.com

I have this program piece:

double stockWeight = 1; if(data[0] > 9 ) stockWeight .

9. Cause of comparing long slower than comparing double stackoverflow.com

I wrote a little program to calculate the first 18 triples (x,y,z) with x , which satisfy x^3+y^3=z^3+1 . While playing around to optimise the total runtime, I discovered, that using double for the .

Читать еще:  Java security nosuchalgorithmexception

10. How to compare two double values in Java stackoverflow.com

Possible Duplicate:
How to resolve a Java Rounding Double issue A simple comparison of two double values in Java creates some problems. Let’s consider the following .

11. Comparing a double against zero stackoverflow.com

I’m new to Java and I’ve been trying to implement an algorithm for finding the roots of a cubical equation. The problem arises when I calculate the discriminant and try to .

12. compare three double numbers coderanch.com

You can’t do it in one statement. Compare one statement to another and store the greatest value in a temp variable. Then compare the temp variable to the third variable and store the greate value in the temp variable. etc, until you’ve gone through all of the values. Math.max() is a useful method for this comparison.

13. Strange result from double comparison coderanch.com

Hello, I have a simple comparison of two double numbers. The same comparison when put in println function gives the correct response (see in the output) but the same comparison if assigned to a boolean value gives a wrong response; I tried to compare numbers inside if condition, in a boolean variable, in reverse for (i.e: gone > MAX_MOVE) but every .

14. Double comparison coderanch.com

Hi, I have requirement to check following value1 = «99999999999.00» value2 = «123122.55»; double d1 = Double.parse(value1) ; double d2 = Double.parse(value2) ; if(d1>d2) < sop("Big") >else < sop("small") >Expected output is Big but giving me small. I tried to print their values & its making 9.99999991E something when I use double parse option. Can someone help me in comparing these .

15. Compare monetary doubles coderanch.com

Hi all, I want to compare 2 values to two decimal places, basically monetary values. I know about precision issues with straight up double comparison using ==, so to check are two values equal (to 2 places) I do the following: . private static final BigDecimal PLUS_ZERO = new BigDecimal(«0.00»); private static final BigDecimal MINUS_ZERO = new BigDecimal(«-0.00»); public boolean compareMoney(final .

Почему Java’s Double.compare(double, double) реализован именно так?

Я смотрел на реализацию compare (double, double) в стандартной библиотеке Java (6). Она гласит::

В чем же заключаются достоинства этой реализации?

edit: «Merits» был (очень) плохой выбор слов. Я хотел знать, как это работает.

4 Ответов

Объяснение находится в комментариях в коде. Java имеет двойные значения как для 0.0 , так и для -0.0 , а также для «not a number» ( NaN ). Для этих значений нельзя использовать простой оператор == . Загляните в источник doubleToLongBits() и в Javadoc для метода Double.equals() :

Заметим, что в большинстве случаев для двоих экземпляры классов Double , d1 и d2 , значение d1.equals(d2) равно true , если и только если

также имеет значение true . Однако, есть два исключения:

  • Если d1 и d2 оба представляют Double.NaN , то метод equals возвращает true , даже хотя Double.NaN == Double.NaN имеет значение false .
  • Если d1 представляет собой +0.0 , а d2 — -0.0 , или наоборот , то равный тест имеет значение false , хотя +0.0 == -0.0 имеет значение true .

Это определение позволяет hash таблицам работать правильно.

@Shoover’s ответ правильный (читай!), но есть немного больше, чем это.

Как javadoc для Double::equals государств:

«This definition allows hash tables to operate properly.»

Предположим, что конструкторы Java решили реализовать equals(. ) и compare(. ) с той же семантикой, что и == в обернутых экземплярах double . Это означало бы, что equals() всегда будет возвращать false для завернутого NaN. Теперь подумайте, что произойдет, если вы попытаетесь использовать обернутый NaN в карте или коллекции.

Это не имеет большого смысла, не так ли?

Другие аномалии будут существовать, потому что -0.0 и +0.0 имеют разные битовые паттерны, но равны в соответствии с == .

Таким образом, дизайнеры Java решили (справедливо IMO) на более сложном (но более интуитивном) определении для этих двойных методов, которые мы имеем сегодня.

Читать еще:  Stringbuilder append java

Заслуга в том, что это самый простой код, который соответствует спецификации.

Одной из общих характеристик начинающих программистов является завышенная оценка исходного кода чтения и заниженная оценка спецификаций чтения . В этом случае спецификация:

делает поведение и причину поведения (согласованность с equals()) совершенно ясными.

Эта реализация позволяет определить действительное число как Поделиться phoebus 13 ноября 2009 в 00:02

Похожие вопросы:

я написал следующие коды моя цель-получить низкое значение doble[] absOfSub , но это дает следующее исключение в строке compared= Double.compare(d2, d1); Exception in thread main.

Я столкнулся с чем-то странным относительно сравнения двойных нулей. В зависимости от того,как инициируются примитивы double zero, метод Double.compare(double, double) может или не может думать, что.

Мой вопрос довольно прост. Почему std::atomic не реализован полностью ? Я знаю, что это связано с блокированным переменным доступом. Но я действительно не понимаю, почему это не должно.

Я пытался выяснить, почему я получаю ‘ ‘ , когда я печатаю переменную char, которая была инициализирована значением по умолчанию ‘u0000’ ? Также я знаю, что float и double имеют значение по.

Я путаю в терминах нижнего регистра double и верхнего регистра Double. в чем разница между double/Double. ? using System; using System.Collections.Generic; using System.Linq; using System.Text;.

Я хотел бы знать точную разницу между BigDecimal и double . Я знаю, что BigDecimal является более точным, чем double , и вы должны использовать первый для расчетов. Почему это более точно? Почему.

Я смотрел на реализацию Double.compare() через F5 в режиме отладки (copy paste) public static int compare(double d1, double d2) < if (d1 values = . ; Double[] doubles = values.toArray(new Double[0]); create(doubles); // wont.

Это небольшая программа для добавления, удаления, вставки в элементы (double) в коллекцию Ilist . class ProgramL < static void Main(string[] args) < IList myList = new.

Сравнить long и double Java

(4) продвижение типов, не?

double val1 = 1.0;
long val2 = (long) val1;

(9) это понятно, я смотрю на (1)

так как их сравнивать-то «правильно»? Мне вот совсем непонятно, почему их нужно сравнивать как-то по особенному, а не продвигать один тип к другому?

Правильно будет так

long val1 = 1;
double val2 = (double) val1;

«long и double нужно сравнить особым образом, все остальные типы приводить к double»

Так почему long не привести к double?

jshell> double a = Double.valueOf(Long.MAX_VALUE)
a ==> 9.223372036854776E18

jshell> long b = Long.MAX_VALUE
b ==> 9223372036854775807

jshell> Double.compare(a, b)
$3 ==> 0

(18) Выдаст точно то же самое:
jshell> double a = Double.valueOf(Long.MAX_VALUE — 1)
a ==> 9.223372036854776E18

jshell> long b = Long.MAX_VALUE
b ==> 9223372036854775807

jshell> Double.compare(a, b)
$3 ==> 0

Просто нужно уяснить что в Double в принципе не может храниться 9223372036854775806 (Long.MAX_VALUE — 1).
происходит потеря точности:

jshell> double d = 9223372036854775806.0
d ==> 9.223372036854776E18

jshell> Double d = 9223372036854775806.0
d ==> 9.223372036854776E18

jshell> d.longValue()
$4 ==> 9223372036854775807

jshell> Double d = 9.223372036854775E18
d ==> 9.2233720368547748E18

jshell> d.longValue()
$14 ==> 9223372036854774784

Таким образом double может хранить ближайшие числа

9223372036854774784 и 9223372036854775807

Короче если по тупому то можно в long засунуть такое число, которое при переносе в double потеряет свою точность.
В то время как классические int прекрасно переносятся и сравниваются с double.

Чтобы сравнить long и double надо знать точность представления типа double на конкретной платформе и привести (округлить) значение.

вот что получилось

static int compareT(T num1, V num2) <

long l1;
long l2;
double d1;
double d2;

if (num1 instanceof Long && num2 instanceof Long) <

return Long.compare(l1, l2);

> else if ((num1 instanceof Long && num2 instanceof Double) || (num1 instanceof Double && num2 instanceof Long)) <
// можно в long засунуть такое число, которое при переносе в double потеряет свою точность

BigDecimal b1 = new BigDecimal(«» + num1);

BigDecimal b2 = new BigDecimal(«» + num2);

d1 = num1.doubleValue();
d2 = num2.doubleValue();
return Double.compare(d1, d2);

так это,мантисса double, это 53 бита,а long это 64
просто,внезапно,регистр сопроцессора это 80 бит и там 64 бита на мантиссу есть,т.к. длинные целые как раз 64 бита.
но типа long double во многих языках нет.

поэтому,можно из long отрезать старшие биты,если они 0,то переводить в double и сравнивать.
если не ноль,то с первого значащего бита отсчитать 53,а оставшийся хвост сраанить с нулем,если он не ноль,то в double такого числа просто нет и можно ничего не сравнивать,если они 0,то переводим в double и срааниваем.

Читать еще:  Assert throws java

Пункт Первый. Java самый лучший язык в мире.
Пункт второй. Если пункт первый не верен, goto Пункт Первый.

(48) дело не в топикстартере, а в «long и double нужно сравнить особым образом». Почему бы их не сравнить как другие числа? Типа из-за того, что на каких-то там мегавеличинах будет неточность?

ты только представь себе размеры. Вот если будет задача учёта всех звёзд во вселенной. ну бред же какой-то.

Why you shouldn’t use == with float and double in Java?

In this article, you are going to learn why you shouldn’t use == with float and double in Java? Especially for checking loop termination condition. Java programmers often make the mistake of using floating point number in a loop and checking condition with the == operator, in the worst case this could create an infinite loop, causing your Java application to hung.

For example, following code will not work as you expect :

You would think that this code will print balance until balance reduced to zero. Since we are doing balance = balance — 0.1 , you would expect it to print something like 10 , 9.9 , 9.8 and so on until it reaches zero. But for your surprise, this will cause an infinite loop in Java, it will never end, Why? because 0.1 is an infinite binary decimal, the balance will never be exactly 0.

This is the reason many programmers, including Joshua Bloch, has suggest to avoid using double and float for monetary calculation in his book Java Puzzlers.

Now, this brings a more pertinent question, how do you compare floating point numbers in Java? if == is not going to work then how can I write a similar loop, because that’s a very general case and it would be unfortunate if you can’t test for decimal points? Let’s find out the right way to compare floating point values in Java in next section.

How to compare float and double values in Java?

As we have seen in the first paragraph that use of == operator can cause an endless loop in Java, but is there a way to prevent that loop from running infinitely? Yes, instead of using equality operator (==), you can use relational operator e.g. less than ( ) to compare float and double values.

By changing the above code as following, you can prevent the loop from infinitely :

If you think a little bit then you will realize that greater than will definitely end this loop, but don’t expect it to print numbers like 9.9 , 9.8 , 9.7 because floating point numbers are a just approximation, they are not exact. Some numbers e.g. 1/3 cannot be represented exactly using float and double in Java.

After running following program on your computer you may end up with something like this

You can see that result is nowhere close to our expectation, and that’s why float and double are not recommended for financial calculation or where the exact result is expected.

Some tips while using float and double in Java

Do all calculation in float/double but for comparison, always compare approximation instead of precise values e.g. instead of checking for 10.00 check for > 9.95 as shown below

One reason, why many programmers make mistake of comparing floating points number with == operator is that, for some fraction it does work properly e.g. if we change 0.1 to 0.5 the loop in question will work properly as shown below :

Alternatively, you can use BigDecimal for exact calculation. You can also try rewriting the same code using BigDecimal class instead of double primitive.

Ссылка на основную публикацию