I’ve tried looking for definitive answers but the only difference I see seems to be based on the precision of the numbers?
Which data type is larger and which one is smaller?
It uses a different representation (floating point) using exponents and mantissa
For details see IEEE754
A double has something called an exponent, which is basically just a scaling factor. This allows the range of double to be much greater, but at the cost of precision.
A long is a simple integer value with no scaling factor.
If you are storing integers, use Long. Your statement that "Advantage of Using Double is that it gives a more wider range for storing Whole Numbers" is incorrect. Both are 64 bits long, but double has to use some bits for the exponent, leaving fewer bits to represent the magnitude. You can store larger numbers in a double but you will lose precision.
In other words, for numbers larger than some upper bound you can no longer store adjacent "whole numbers"... given an integer value above this threshold, the "next" possible double will be more than 1 greater than the previous number.
For example
public class Test1
{
public static void main(String[] args) throws Exception
{
long long1 = Long.MAX_VALUE - 100L;
double dbl1 = long1;
long long2 = long1+1;
double dbl2 = dbl1+1;
double dbl3 = dbl2+Math.ulp(dbl2);
System.out.printf("%d %d\n%f %f %f", long1, long2, dbl1, dbl2, dbl3);
}
}
This outputs:
9223372036854775707 9223372036854775708
9223372036854776000.000000 9223372036854776000.000000 9223372036854778000.000000
Note that
- The double representation of Long.MAX_VALUE-100 does NOT equal the original value
- Adding 1 to the double representation of Long.MAX_VALUE-100 has no effect
- At this magnitude, the difference between one double and the next possible double value is 2000.
Another way of saying this is that long has just under 19 digits precision, while double has only 16 digits precision. Double can store numbers larger than 16 digits, but at the cost of truncation/rounding in the low-order digits.
If you need more than 19 digits precision you must resort to BigInteger, with the expected decrease in performance.
This looks like the wrong battle:
From the Java Tutorial
The long data type is a 64-bit signed two's complement integer. It has a minimum value of -9,223,372,036,854,775,808 and a maximum value of 9,223,372,036,854,775,807 (inclusive).
That's pretty close to 19 significant digits
From Wikipedia
This gives from 15 - 17 significant decimal digits precision.
So, despite its apparent "superiority" Double will serve you worse than Long. And I'm merely guessing here, but intuitively I'd say serialization/deserialization of floating point types are costlier operations than the same operations on integral data types, but even if there are differences they will be quite small on modern systems.
So, when working with integers, stick to Long.
Double.MAX_VALUE is the maximum value a double can represent (somewhere around 1.7*10^308).
This should end in some calculation problems, if you try to subtract the maximum possible value of a data type.
Even though when you are dealing with money you should never use floating point values especially while rounding this can cause problems (you will either have to much or less money in your system then).
Resurrecting the dead here, but just in case someone stumbles against this like myself. I know where to get the maximum value of a double, the (more) interesting part was to how did they get to that number.
double has 64 bits. The first one is reserved for the sign.
Next 11 represent the exponent (that is 1023 biased). It's just another way to represent the positive/negative values. If there are 11 bits then the max value is 1023.
Then there are 52 bits that hold the mantissa.
This is easily computed like this for example:
public static void main(String[] args) {
String test = Strings.repeat("1", 52);
double first = 0.5;
double result = 0.0;
for (char c : test.toCharArray()) {
result += first;
first = first / 2;
}
System.out.println(result); // close approximation of 1
System.out.println(Math.pow(2, 1023) * (1 + result));
System.out.println(Double.MAX_VALUE);
}
You can also prove this in reverse order :
String max = "0" + Long.toBinaryString(Double.doubleToLongBits(Double.MAX_VALUE));
String sign = max.substring(0, 1);
String exponent = max.substring(1, 12); // 11111111110
String mantissa = max.substring(12, 64);
System.out.println(sign); // 0 - positive
System.out.println(exponent); // 2046 - 1023 = 1023
System.out.println(mantissa); // 0.99999...8
This is because of the loss of precision while converting long to double
double d1 = (double)Long.MAX_VALUE;
double d2 = Long.MAX_VALUE + 1.0;
System.out.println(d1);
System.out.println(d2);
it gives the same numbers
9.223372036854776E18
9.223372036854776E18
long has 32 bits and double's significand has 53 bits http://en.wikipedia.org/wiki/Double-precision_floating-point_format. In decimal terms, max long = 9223372036854775807, it is 19 digits, and double can hold 17 max
Long.MAX_VALUE has 63 significant bits. A double cannot exactly represent any number with more than 53 significant bits. If you want to do exact calculations with integers bigger than Long.MAX_VALUE I suggest using java.math.BigInteger.
import java.math.BigInteger;
public class Test {
public static void main(String[] args) {
BigInteger longMax = BigInteger.valueOf(Long.MAX_VALUE);
BigInteger plusOne = longMax.add(BigInteger.ONE);
System.out.println(longMax.equals(plusOne));
}
}
That method can't return true. That's the point of Long.MAX_VALUE. It would be really confusing if its name were... false. Then it should be just called Long.SOME_FAIRLY_LARGE_VALUE and have literally zero reasonable uses. Just use Android's isUserAGoat, or you may roll your own function that always returns false.
Note that a long in memory takes a fixed number of bytes. From Oracle:
long: The long data type is a 64-bit signed two's complement integer. It has a minimum value of -9,223,372,036,854,775,808 and a maximum value of 9,223,372,036,854,775,807 (inclusive). Use this data type when you need a range of values wider than those provided by int.
As you may know from basic computer science or discrete math, there are 2^64 possible values for a long, since it is 64 bits. And as you know from discrete math or number theory or common sense, if there's only finitely many possibilities, one of them has to be the largest. That would be Long.MAX_VALUE. So you are asking something similar to "is there an integer that's >0 and < 1?" Mathematically nonsensical.
If you actually need this for something for real then use BigInteger class.
You can't. If you have a method called isBiggerThanMaxLong(long) it should always return false.
If you were to increment the bits of Long.MAX_VALUE, the next value should be Long.MIN_VALUE. Read up on twos-complement and that should tell you why.