Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modulus with doubles in Java

How do you deal with Java's weird behaviour with the modulus operator when using doubles?

For example, you would expect the result of 3.9 - (3.9 % 0.1) to be 3.9 (and indeed, Google says I'm not going crazy), but when I run it in Java I get 3.8000000000000003.

I understand this is a result of how Java stores and processes doubles, but is there a way to work around it?

like image 669
Andy Avatar asked Jul 12 '10 09:07

Andy


People also ask

Does modulus work with doubles C?

The modules operator works with integer values i.e. modulus operator is used to find the remainder of two integer numbers. If the numbers are float or double the the modulus operators doesn't work.

Can you use modulus with floats?

Yes, %(modulo) operator isn't work with floats and double.. if you want to do the modulo operation on large number you can check long long int(64bits) might this help you. still the range grater than 64 bits then in that case you need to store the data in .. string and do the modulo operation algorithmically.

What does the modulus (%) operator do?

The modulo operator, denoted by %, is an arithmetic operator. The modulo division operator produces the remainder of an integer division.

Can you use modulus in Java?

Although Java has a remainder operator for int and long types, it has no modulus function or operator.


1 Answers

Use a precise type if you need a precise result:

    double val = 3.9 - (3.9 % 0.1);
    System.out.println(val); // 3.8000000000000003

    BigDecimal x = new BigDecimal( "3.9" );
    BigDecimal bdVal = x.subtract( x.remainder( new BigDecimal( "0.1" ) ) );
    System.out.println(bdVal); // 3.9

Why 3.8000...003? Because Java uses the FPU to calculate the result. 3.9 is impossible to store exactly in IEEE double precision notation, so it stores 3.89999... instead. And 3.8999%0.01 gives 0.09999... hence the result is a little bit bigger than 3.8.

like image 81
Aaron Digulla Avatar answered Sep 17 '22 05:09

Aaron Digulla