I cannot fully understand the in/compatibility between long and double;

The following code points out that long can be converted into double, but it's illegal the contrary.

What puzzles me is that both primitives are ranged as 64 bit number.

So how is that possible?

- 2

Where as long can not handle factions/decimal numbers, but only whole numbers.

Given your example code

**x**is a whole number of 1000.

It then automatically gets converted to a double when you declare

**y**.

Now

**y**is 1000.00, or something close to that because it's a double.

1000.00 cannot be converted to

**int**without the loosing the decimal places. In doing so you may lose some precision.

This is somewhat related to this posting/blog entry

Does 1.0 equal 0.9999999999999999...?

Which attempts to explain some of the concerns with dealing to floating point numbers in regards to comparisons.

“The strongest of all warriors are these two — Time and Patience.” ― Leo Tolstoy, War and Peace

- 2

`long`.

`1_000`is an

`int`literal, which requires conversion to a

`long`before you can use it. The

`long`form of the number is

`1_000L`.

What PL has said is the explanation for a basic language requirement: a

`double`is regarded as a “wider” datatype that a

`long`, so you can implicitly widen one way, but you cannot convert the other way without a cast. As PL has hinted, the cast will lose any fractional part of the number.

You can also get loss of precision the other way; it is possible to fit 1234567891011121314L into a

`long`, but there is no guarantee that it can be exactly represented as a

`double`.

1000 is one of the numbers that can be represented exactly as a

`double`.

Pete Letkeman wrote:Please remember that a double can handle factions/decimal numbers for instance 3.141592654 as well as whole numbers.

Where as long can not handle factions/decimal numbers, but only whole numbers.

Given your example codexis a whole number of 1000.

It then automatically gets converted to a double when you declarey.

Nowyis 1000.00, or something close to that because it's a double.

1000.00 cannot be converted tointwithout the loosing the decimal places. In doing so you may lose some precision.

...

Hi Pete,

thanks for the answer.

So

**double**cannot get back to

**long**because of the floating point, I mean the compiler thinks:" if there was decimal digits in double then the program would loose them. Let's advise of the possible lossy conversion!".

- 2

“The strongest of all warriors are these two — Time and Patience.” ― Leo Tolstoy, War and Peace

- 2

Daniele Barell wrote:So double cannot get back to long because of the floating point

It cannot go back without losing precision, obviously. In general it can, you just need explicitly cast it to long.

Campbell Ritchie wrote:You are not using the number as a

long.1_000is anintliteral, which requires conversion to alongbefore you can use it. Thelongform of the number is1_000L.

I see.

But it's not a requirement. I mean I can use

`x`without convert the literal to long:

Campbell Ritchie wrote:What PL has said is the explanation for a basic language requirement: a

doubleis regarded as a “wider” datatype that along, so you can implicitly widen one way, but you cannot convert the other way without a cast. As PL has hinted, the cast will lose any fractional part of the number.

OK

Campbell Ritchie wrote:You can also get loss of precision the other way; it is possible to fit 1234567891011121314L into a

long, but there is no guarantee that it can be exactly represented as adouble.

So why the compiler enables me to convert a long into double?

by the way, you are right:

I'm not a math wiz...What's the meaning of the last 'E18'?

Liutauras Vilda wrote:

Daniele Barell wrote:So double cannot get back to long because of the floating point

It cannot go back without losing precision, obviously. In general it can, you just need explicitly cast it to long.

Hi Liutaras,

thanks for the clarification!

"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 not only does precision vary, but so does the domain of the representable number set.

I'd have to check, but I think that Java is one of the languages that also supports the construct "long double". The implied noun here is float, since upconversion makes floats of integers, so "double" is the determining word.

An IDE is no substitute for an Intelligent Developer.

That code has an implicit cast it. You have anDaniele Barell wrote:. . . I mean I can use

xwithout convert the literal to long:

`int`expression to the right of the = sign and the JVM will interpret that as

`long x = (long)(1_000);`

Since the expression on the right is a constant expression, what many people call a compile‑time constant, the type conversion may be done by the compiler. If it is, it can be seen in the bytecode. You can view the bytecode with

`. If you look in the Java® Language Specification (=JLS), you will find that`

__javap -c LongDouble__`long`→

`double`is one of the 19 “widening primitive conversions”. These are specifically permitted by the language specification under all circumstances. If you scroll down, you will find that

If you scroll down a bit more, you will find there are also 22 “narrowing primitive conversions”. You will see from the example that they all require casts; if you attempt any of those conversions without a cast, the compiler must fail to accept the code, but the compiler error message about “possible loss of precision” isn't very clear.A widening primitive conversion from int to float, or from long to float, or from long to double, may result in loss of precision - that is, the result may lose some of the least significant bits of the value.

As it said earlier, “widening” conversions are always permitted.. . . So why the compiler enables me to convert a long into double? . . .

If you go back to the JLS link I gave above, you will see there are comments about range, saying that casting

`double`→

`float`may cause small values to degenerate to 0f and large values to degenerate to ∞. That suggests that a number datatype is regarded as “wider” if its range of permissible values is greater, meaning there are more values between the largest and the smallest. A

`double`and a

`long`each occupy 64 bits, and the

`long`can exactly define every whole number in its range. But the

`double`has a much larger range, so it must miss out some values. I learnt about that first from the Deitel and Deitel Java5 book. There are ten

`long`values between 1234567891011121310L and 1234567891011121320L(exc), but there are not ten different

`double`values in that range, so the nearest

`double`has to be chosen. In fact the output you obtained suggests to me that there are no

`double`values in that range, which is why it ends 141 not 13x.

Because you didn't specify any formatting, the output defaults to printing the fewest numbers necessary to identify the nearest distinct value. That turns out to be 1,234,567,890,101,114,100 but the default format is so‑called scientific format which on paper looks like 1.23456789101112141×10¹⁸, but older computers didn't have the pretty superscripts, so they write E18 instead of ×10¹⁸. Read that as meaning you move the decimal point 18 places to the right; in this case you will have to add a few 0s on the right.. . . What's the meaning of the last 'E18'?

If you are supposed to move the decimal point to the left, there will be a − after the E.

I am now going into hiding for embarrassment about how many posts I have

[edit]Additonal: I see that the 121314 at the right end of the number has turned into 14100 so the precision is worse than I thought. It also might mean that I have missed out a 0 at the right of the number I was discussing.

An integer is self-contained and it is at its heart a unitary value. A floating-point number is not. Floats have an exponent part and a mantissa part. The exponent scales the mantissa value. The mantissa is considered as a binary fraction - that is, 0.1 would have a value of 1/2. Given that, an exponent of 1 (meaning 2**1) and a mantissa of 0.100000000... would have an integral value of 1.

The difference between float, double and long double is primarily in the available amount of bit positions. The total bit occupancy of a float is 32 bits, a double is 64 bits and a long double is 128 bits.

Although, if memory serves, the IEEE spec does allow some extra bits for exponent values as well (IBM's S/360 version always had 8 bits for exponent and everything else was mantissa).

For a given number of exponent bits, adding bits to the overall value length does not increase the

**range**of the number, but rather its

**precision.**(also known as

*epsilon.*). So downscaling from a double to a float, for example, would be the equivalent of chopping the value 9.3333333333 down to 9.333333. The approximate values are the same, but obviously not their exact values. Since the mantissa is a binary fraction and not a decimal one, a lot of decimal fractions are crude to begin with. 0.5 and 0.25 are easy (precise), but 0.1 is not (irrational, if I've got my terminology correct).

In the event that your floating-point system allows different-sized exponent bit allocations, downscaling where the target exponent cannot hold the original exponent value can potentially blow the number out of range. But in general, that should not result in infinity, but in a NaN value, since it's not literally infinity. And, of course raise a range exception.

So you have 2 vulnerabilities. First, that you will lose precision - downwards for positive numbers, upwards for negative numbers, and the loss of precision is not related to the related (nearest) integer value.

Secondly, that you will exceed the range of the integral reach of the number (exponent size).

Loss of precision is annoying, but non-fatal. Unless you accumulate enough erosion to, say, destroy an interplanetary exploration vehicle or steal from someone's paycheck. Loss of exponent range, on the other hand is an immediate problem, since it puts an immediate end to all further computation.

An IDE is no substitute for an Intelligent Developer.