double is made of 1 bit sign 52 bit mantissa and 11 bit exponent and long is made of 1 bit sign and 63 bit number. So double can have larger values, and they both take 64 bits in your memory. So double has the precision of at most 16 digits and long of at most 19 digits. (Also, a double can have a value of Infinity) If you're looking for an object that can store very large numbers, use BigInteger or BigDecimal, their value is only limited by how much memory your computer has and they can do precise math. Answer from Chemical-Asparagus58 on reddit.com
🌐
Reddit
reddit.com › r/learnjava › why does adding long to double as the result we got double?
r/learnjava on Reddit: Why does adding long to double as the result we got double?
August 8, 2022 -

let’s say we have: long l1 = 9L; double d1 = 3.5;

double result = l1 + d1;

Just learned that arithmetic operations are done only on: int, long,double, float.

And I know about promoting data type to higher by occupation in memory. But both long and double occupies 8 bytes. So why the result is double?

Top answer
1 of 4
11
double is the wider data type. A long only contains the direct binary representation of the stored number while a double uses IEEE-754 floating point format and by doing so it has a much wider range. Further: converting to long would be a lossy conversion as the decimals would get lost. Generally, non-lossy conversions to wider data types are preferred.
2 of 4
3
The long value is converted to a double before the addition occurs, and double addition results in a double. All long values 'fit' in the range of a double, not all double values fit in the range of long. If the conversion-precedence worked the other way then you would be automatically discarding precision over ranges of values that are far more typical to encounter than the small degree of precision you lose going from long to double on value ranges that are atypically used. eg. long before = 9223372036854775797L; double d = before; long after = (long) d; // 9223372036854775807L; The difference between before and after is 2 decimal digits of precision error. double before = 0.123456789D; long l = (long) before; double after = l; The difference between before and after is 9 decimal digits of precision. So the 'why' in your question... Because this is the more useful of the two choices converting between two equal 'sized' types. Now why they decided to silently allow precision loss, that's tougher - I expect there's a fair number of developers that wish this was not the case (and languages like Rust are far more strict in this regard).
🌐
RETIT
retit.de › performance-in-detail-long-vs-double-in-java-2
Performance in Detail: Long vs. Double in Java – RETIT
April 23, 2018 - But still, even when looking at the boxed types Long and Double, the only attribute in both classes is the wrapped primitive, so Double objects should consume the same amount of memory as Long objects.
🌐
Reddit
reddit.com › r/java › double vs bigdecimal in financial programming
r/java on Reddit: Double vs BigDecimal in financial programming
July 15, 2016 -

Everyone says that BigDecimal should be used when dealing with money but it’s much slower and takes more memory than double. I would think this would be especially important in high frequency low-latency applications like trading. Do people actually use BigDecimal in such systems or do they use doubles with some kind of workaround to handle the precision issue?

Edit: I do have experience working on trading and risk systems and I see doubles used much more often than BigDecimal so I was curious to see if this is more common in actual practice. Most of the systems I worked on only need precision to the penny so I wonder if that’s the reason?

Also, BigDecimal is a pain to use and code written with it look much uglier than plain doubles.

Top answer
1 of 3
26

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

  1. The double representation of Long.MAX_VALUE-100 does NOT equal the original value
  2. Adding 1 to the double representation of Long.MAX_VALUE-100 has no effect
  3. 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.

2 of 3
3

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.

🌐
Blogger
javahungry.blogspot.com › 2022 › 11 › long-vs-double.html
Java long vs double | Java Hungry
Java developers tutorials and coding. ... In this post, I will be sharing what is the difference between long and double in Java. Both are primitive data types.
Find elsewhere
Top answer
1 of 4
7

The absolute quantity of information that you can store in 64 bit is of course the same.

What changes is the meaning you assign to the bits.

In an integer or long variable, the codification used is the same you use for decimal numbers in your normal life, with the exception of the fact that number two complement is used, but this doesn't change that much, since it's only a trick to gain an additional number (while storing just one zero instead that a positive and a negative).

In a float or double variable, bits are split in two kinds: the mantissa and the exponent. This means that every double number is shaped like XXXXYYYYY where it's numerical value is something like XXXX*2^YYYY. Basically you decide to encode them in a different way, what you obtain is that you have the same amount of values but they are distribuited in a different way over the whole set of real numbers.

The fact that the largest/smallest value of a floating number is larger/smaller of the largest/smalles value of a integer number doesn't imply anything on the amount of data effectively stored.

2 of 4
2

A double can store a larger number by having larger intervals between the numbers it can store, essentially. Not every integer in the range of a double is representable by that double.

More specifically, a double has one bit (S) to store sign, 11 bits to store an exponent E, and 52 bits of precision, in what is called the mantissa (M).

For most numbers (There are some special cases), a double stores the number (-1)^S * (1 + (M * 2^{-52})) * 2^{E - 1023}, and as such, when E is large, changing M by one will make a much larger change in the size of the resulting number than one. These large gaps are what give doubles a larger range than longs.

🌐
Pediaa
pediaa.com › home › technology › it › programming › what is the difference between long and double in java
What is the Difference Between long and double in Java - Pediaa.Com
May 30, 2019 - The value of long ends with letter ... is 0. “double” is a data type that stores floating point numbers. It is similar to a float data type. Unlike, a float which stores 32 bit IEEE 745 floating point numbers, double stores 64-but IEEE 754 floating point numbers...
🌐
Coderanch
coderanch.com › t › 328469 › java › comparision-double-long
comparision between double and long (Java in General forum at Coderanch)
Books: Java Threads, 3rd Edition, Jini in a Nutshell, and Java Gems (contributor) ... 123456789.00000001 == 123456789.0" should return true. But I want them as false 123456789.00000001 == 123456789.0000000 should return me false. How do I do that? Rizwan SCJA, SCJP, SCWCD, SCBCD, SCDJWS. ... If you remove string and give numbers as double instead of string it says equal(compare method returns 0) BigDecimal bd1 = new BigDecimal(1234567891.00000001); BigDecimal bd2 = new BigDecimal(1234567891); bd1.compareTo(bd2) returns 0.
🌐
Quora
quora.com › What-is-the-difference-between-an-int-a-long-a-double-and-a-decimal-in-Java
What is the difference between an int, a long, a double and a decimal in Java? - Quora
Answer (1 of 5): There are eight primitive datatypes supported by Java. Primitive datatypes are predefined by the language and named by a keyword. int * Int data type is a 32-bit signed two's complement integer. * Minimum value is - 2,147,483,648 (-2^31) * Maximum value is 2,147,483,647(incl...
Top answer
1 of 7
117

With the possible exception of "short", which arguably is a bit of a waste of space-- sometimes literally, they're all horses for courses:

  • Use an int when you don't need fractional numbers and you've no reason to use anything else; on most processors/OS configurations, this is the size of number that the machine can deal with most efficiently;
  • Use a double when you need fractional numbers and you've no reason to use anything else;
  • Use a char when you want to represent a character (or possibly rare cases where you need two-byte unsigned arithmetic);
  • Use a byte if either you specifically need to manipulate a signed byte (rare!), or when you need to move around a block of bytes;
  • Use a boolean when you need a simple "yes/no" flag;
  • Use a long for those occasions where you need a whole number, but where the magnitude could exceed 2 billion (file sizes, time measurements in milliseconds/nanoseconds, in advanced uses for compacting several pieces of data into a single number);
  • Use a float for those rare cases where you either (a) are storing a huge number of them and the memory saving is worthwhile, or (b) are performing a massive number of calculations, and can afford the loss in accuracy. For most applications, "float" offers very poor precision, but operations can be twice as fast -- it's worth testing this on your processor, though, to find that it's actually the case! [*]
  • Use a short if you really need 2-byte signed arithmetic. There aren't so many cases...

[*] For example, in Hotspot on Pentium architectures, float and double operations generally take exactly the same time, except for division.

Don't get too bogged down in the memory usage of these types unless you really understand it. For example:

  • every object size is rounded to 16 bytes in Hotspot, so an object with a single byte field will take up precisely the same space as a single object with a long or double field;
  • when passing parameters to a method, every type takes up 4 or 8 bytes on the stack: you won't save anything by changing a method parameter from, say, an int to a short! (I've seen people do this...)

Obviously, there are certain API calls (e.g. various calls for non-CPU intensive tasks that for some reason take floats) where you just have to pass it the type that it asks for...!

Note that String isn't a primitive type, so it doesn't really belong in this list.

2 of 7
19

A java int is 32 bits, while a long is 64 bits, so when you need to represent integers larger than 2^31, long is your friend. For a typical example of the use of long, see System.currentTimeMillis()

A byte is 8 bits, and the smallest addressable entity on most modern hardware, so it is needed when reading binary data from a file.

A double has twice the size of a float, so you would usually use a double rather than a float, unless you have some restrictions on size or speed and a float has sufficient capacity.

A short is two bytes, 16 bits. In my opinion, this is the least necessary datatype, and I haven't really seen that in actual code, but again, it might be useful for reading binary file formats or doing low level network protocols. For example ip port numbers are 16 bit.

Char represents a single character, which is 16 bits. This is the same size as a short, but a short is signed (-32768 to 32767) while a char is unsigned (0 to 65535). (This means that an ip port number probably is more correctly represented as a char than a short, but this seems to be outside the intended scope for chars...)

For the really authorative source on these details, se the java language specification.

🌐
TestMu AI Community
community.testmuai.com › ask a question
How does serialization performance compare between `long` and `double` in Java? - TestMu AI Community
April 1, 2025 - Both long and double take 8 bytes in Java, and while double offers a wider range for storing whole numbers, long might still be sufficient for many use cases. How does java long vs double serialization and deserializatio…
🌐
Reddit
reddit.com › r/java › long is faster than int, short and byte are not that far behind int in terms of mathematical speed in java
r/java on Reddit: Long is faster than int, Short and Byte are not that far behind Int in terms of mathematical speed in Java
December 23, 2025 -

So i am learning java, and my mentor is a senior with deep roots in the field. Anyways on one of our weekly checkup calls he asked me a simple question whats the difference in primitive data types and is there a reason to use short over int.

Well i couldnt answer this novel question and so i went on searching and i couldnt find a proper answer for the second part. While most seemed to agree int would be faster than short, the opinions on just HOW much faster varied alot.

I saw this as a learning opportunity (Also i thought itd be interesting to start making videos about this kind of stuff i learn)

So i ran a few (albeit amateur) tests to see the differences. First i did just sums for int vs short with shorts being much slower. But i learned about blackholes and like jvm can sometimes over optimize your code etc so i kind of caved and got some help from claude for what mathematical equation would be best to see the differences. Also since bytes only go up to a few numbers i had to nest it 3 times in loops so that i had a long enough loop.
Also heres a short vid

Here are the results

along with the code (for the second bigger chart)

package com.yourcompany;
import org.openjdk.jmh.annotations.*;
import java.util.concurrent.TimeUnit;

(Scope.Thread)
(Mode.AverageTime)
(TimeUnit.MICROSECONDS)
(value = 1, warmups = 2)
(iterations = 3)
public class MyBenchmark {
    // Using byte-sized loops (max value 127)
    private static final byte OUTER_LOOPS = 32;
    private static final byte MIDDLE_LOOPS = 16;
    private static final byte INNER_LOOPS = 8;

    u/Benchmark
    public byte testByte() {
        byte z = 42;
        for (byte i = 0; i < OUTER_LOOPS; i++) {
            for (byte j = 0; j < MIDDLE_LOOPS; j++) {
                for (byte k = 0; k < INNER_LOOPS; k++) {
                    int t = (z * 31) + i + j + k;
                    z = (byte) (t ^ (t >>> 8));
                    z = (byte) ((z / 7) + (z % 64));
                }
            }
        }
        return z;
    }

    u/Benchmark
    public short testShort() {
        short z = 42;
        for (byte i = 0; i < OUTER_LOOPS; i++) {
            for (byte j = 0; j < MIDDLE_LOOPS; j++) {
                for (byte k = 0; k < INNER_LOOPS; k++) {
                    int t = (z * 0x9E37) + i + j + k;
                    z = (short) (t ^ (t >>> 16));
                    z = (short) ((z / 7) + (z % 1024));
                }
            }
        }
        return z;
    }

    u/Benchmark
    public int testInt() {
        int z = 42;
        for (byte i = 0; i < OUTER_LOOPS; i++) {
            for (byte j = 0; j < MIDDLE_LOOPS; j++) {
                for (byte k = 0; k < INNER_LOOPS; k++) {
                    int t = (z * 0x9E3779B9) + i + j + k;
                    z = (t ^ (t >>> 16));
                    z = (z / 7) + (z % 1024);
                }
            }
        }
        return z;
    }

    u/Benchmark
    public long testLong() {
        long z = 42L;
        for (byte i = 0; i < OUTER_LOOPS; i++) {
            for (byte j = 0; j < MIDDLE_LOOPS; j++) {
                for (byte k = 0; k < INNER_LOOPS; k++) {
                    long t = (z * 0x9E3779B97F4A7C15L) + i + j + k;
                    z = (t ^ (t >>> 32));
                    z = (z / 7) + (z % 4096);
                }
            }
        }
        return z;
    }

    u/Benchmark
    public float testFloat() {
        float z = 42.0f;
        for (byte i = 0; i < OUTER_LOOPS; i++) {
            for (byte j = 0; j < MIDDLE_LOOPS; j++) {
                for (byte k = 0; k < INNER_LOOPS; k++) {
                    float t = (z * 1.618033988749f) + i + j + k;
                    z = t * t;
                    z = (z / 7.0f) + (z % 1024.0f);
                }
            }
        }
        return z;
    }

    u/Benchmark
    public double testDouble() {
        double z = 42.0;
        for (byte i = 0; i < OUTER_LOOPS; i++) {
            for (byte j = 0; j < MIDDLE_LOOPS; j++) {
                for (byte k = 0; k < INNER_LOOPS; k++) {
                    double t = (z * 1.618033988749894848) + i + j + k;
                    z = t * t;
                    z = (z / 7.0) + (z % 4096.0);
                }
            }
        }
        return z;
    }

    u/Benchmark
    public char testChar() {
        char z = 42;
        for (byte i = 0; i < OUTER_LOOPS; i++) {
            for (byte j = 0; j < MIDDLE_LOOPS; j++) {
                for (byte k = 0; k < INNER_LOOPS; k++) {
                    int t = (z * 0x9E37) + i + j + k;
                    z = (char) (t ^ (t >>> 16));
                    z = (char) ((z / 7) + (z % 512));
                }
            }
        }
        return z;
    }
}
Top answer
1 of 5
134
short and byte do not exist in Java outside arrays. If you declare a short or byte then it gets treated as an int in the java bytecode. Consider this code: class Nums { public static void main(String[] args) { long a = 1L; int b = 2; short c = 3; byte d = 4; System.out.println(a + b + c + d); } } This results in the following bytecode (javap -c -s is your friend here). class Nums { Nums(); descriptor: ()V Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."":()V 4: return public static void main(java.lang.String[]); descriptor: ([Ljava/lang/String;)V Code: 0: lconst_1 1: lstore_1 2: iconst_2 3: istore_3 4: iconst_3 5: istore 4 7: iconst_4 8: istore 5 10: getstatic #7 // Field java/lang/System.out:Ljava/io/PrintStream; 13: lload_1 14: iload_3 15: i2l 16: ladd 17: iload 4 19: i2l 20: ladd 21: iload 5 23: i2l 24: ladd 25: invokevirtual #13 // Method java/io/PrintStream.println:(J)V 28: return } Notice this bit: 0: lconst_1 1: lstore_1 2: iconst_2 3: istore_3 4: iconst_3 5: istore 4 7: iconst_4 8: istore 5 Anything iconst means "load integer (i32be) value" and istore means "store integer on stack". Anything lconst or lstore means load/store a long (i64be). The i2l lines are casting an int to a long. That is why a byte or a short will never be faster than an int when not dealing with arrays. That is because all usage actually compiles to an integer operation, with any potential masking occurring as additional overhead. ETA: this is talking about the VM bytecode instruction set with respect to lack of short/byte support. It is nothing to do with the object model itself, naturally those can store smaller types otherwise every data type would consume 4 or 8 bytes of memory.
2 of 5
86
There is almost nothing in programming more worthless than micro-benchmarks. Some of what you're seeing may be different on different CPU's (i.e. Intel vs Mac) and some depends on what compiler flags you have. But when are you ever going to use a tight loop to calculate the same value over and over in the real world? This is the type of code that we see over and over again saying "my programming language is better than yours because it can do useless loops really fast".
🌐
Coderanch
coderanch.com › t › 689430 › java › primitive-long-double-compatibility
primitive long and double compatibility (Beginning Java forum at Coderanch)
Grammar lesson: "long" is an adjective - describing the implied noun (integer) "double" is also an adjective - describing the implied noun float (floating-point number, to be precise) In computer grammar terms, the "adjectives" are called modifiers. So you have 2 different base types and therefore ...