This week's book giveaway is in the Programmer Certification forum.
We're giving away four copies of OCP Oracle Certified Professional Java SE 11 Programmer I Study Guide: Exam 1Z0-815 and have Jeanne Boyarsky & Scott Selikoff on-line!
See this thread for details.
Win a copy of OCP Oracle Certified Professional Java SE 11 Programmer I Study Guide: Exam 1Z0-815 this week in the Programmer Certification forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Liutauras Vilda
  • Junilu Lacar
  • Jeanne Boyarsky
  • Bear Bibeault
Sheriffs:
  • Knute Snortum
  • Devaka Cooray
  • Tim Cooke
Saloon Keepers:
  • Tim Moores
  • Stephan van Hulst
  • Tim Holloway
  • Ron McLeod
  • Carey Brown
Bartenders:
  • Paweł Baczyński
  • Piet Souris
  • Vijitha Kumara

Demonstrating the rules of Numeric Promotion

 
Ranch Hand
Posts: 58
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The first rule of Java Numeric Promotion says:
"If two values have different data types, Java will automatically promote one of the values to the larger of the two data types".

However, I got some unexpected output from the code:

Promoting b, which is: 6.78

Both variables appear to be assigned to the same value, 6.78. So why would the float be larger than the double, since a float data type is 4 bytes and a double data type is 8 bytes? What happened?
 
author & internet detective
Posts: 39624
784
Eclipse IDE VI Editor Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Doubles aren't stored as exact precision. (Not sure if floats are, but I imagine the same).

This is why using == on a double is a bad idea. Instead, people should compare with a tolerance. For example
 
Marshal
Posts: 14388
240
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Judging from that code, it appears you misunderstood what is meant by "promoting to the larger of the two data types."

It means that if you have an int and a long, the int will be promoted to a long because long is the larger of the two data types.

Likewise, if you have float and a double, the float will be promoted to a double because the double is the larger of the two data types. So, if you have a float value of 5.0 and a double value of 4.0, the float value will be promoted to a double 5.0

If you change your code so that you're using int and long instead of float and double and change the values to be some integer value (the same for both variables), then you'll find that your code prints out nothing.
 
Marshal
Posts: 66263
250
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Jeanne Boyarsky wrote:. . . Not sure if floats are, but I imagine the same . . .

Yes, floats and doubles are both stored in the IEEE754 format, so they have the same precision problems, but worse for floats. I presume promotion would entail filling the mantissa with 0s, so the promoted value will not be the same as the double. I don't know whether the Java® Language Specification (=JLS) says anything more specific.
Also remember the promotion only occurs in the inequalities in lines 9 and 12. The values in lines 10 and 13 are not promoted because the float and double don't meet. You have to imagine that you are writing (double)a > (double)b; that is how the promotion works. It is permissible to cast something to the same type it already has. I think you have been given confusing information about what promotion means. You have been told it goes to the “larger” type, but it atually is towards the “wider” type as described here in the JLS. It does not mean that the promoted variable has a larger value than the un‑promoted one. Obviously the imprecision of representing 6.78 in 32 bits is more in the larger direction than the imprecision of representing 6.87 in 64 bits. Maybe you would get different results with 7.89 or 1.23. I don't know.

Anyway, if you are posting on “Beginning”, there are two additional things you should know:-
  • 1: You don't need to know about floating‑point promotion.
  • 2: Avoid the problem completely; don't use floats.
  •  
    Sam Peterson
    Ranch Hand
    Posts: 58
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    For the sake of number promotion testing, it would be very helpful if you could print out the data type of a value. I wasn't the first one to think about this idea, but does anybody know the answer?
     
    Junilu Lacar
    Marshal
    Posts: 14388
    240
    Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    I don't know of a way to programmatically check what the actual type of a local "var" declaration is but if you just want to experiment with a few different value types, go to JShell.

    Here's my experiment:

    Otherwise, if you're not using var to leverage type inference, then you're using explicitly declared types. In that case, it should be straightforward to apply the numeric promotion and conversion rules specified in the Java Language Specification. If you're explicitly declaring types, wondering what the data type of a value is kind of like asking "How big is water?" The answer is, "as big as the container that's holding it."  

    I'm not sure what's confusing for you but you really just need to see what the declared type is. Automatic promotion and conversion is mainly governed by the declared type. That's ultimately what will determine the final size/type of the value you're assigning to a variable.
     
    Junilu Lacar
    Marshal
    Posts: 14388
    240
    Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
    • Likes 2
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Actually, it's not that hard to write a class that you can use to experiment with:

    and here are some results of my experimentation with that in JShell:

     
    Campbell Ritchie
    Marshal
    Posts: 66263
    250
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    Sam Peterson wrote:. . . I wasn't the first one to think about this idea. . .

    That link does indeed show the standard way to print the runtime type of a reference variable. It even works for arrays, but the output looks strange if you aren't used to it. You can't do the same for primitives becaue they don't have a getClass() method. They don't have any methods in fact. Junilu has shown that the compiler can predict what the runtime type of s1 + s2 is, but not the individual variables:-

    The same code as Junilu's wrote:jshell> WhatIs.typeOf(s1 + s2)
    $15 ==> "Primitive: int"

    You cannot, as far as I know, see that during that calculation, both shorts are promoted to ints, and revert to being shorts, their declared type, when the arithmetic has finished.
     
    Sam Peterson
    Ranch Hand
    Posts: 58
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    After much experimenting, I think I have got an understanding of numeric promotion rules. Please let me know if there are any misunderstandings in the code comments:

    With all of that, I think I have simplified numeric promotion rules down to two simple facts:

    1.) anytime you have a data type smaller than an integer on the left-hand side of the assignment operator, you need to either provide a cast or use a compound assignment operator.

    2.) anytime you have an operand variable on the right-hand side of the assinment operator whose data type is larger than the data type of the operand variable on the left-hand side of the assignment operator, you get a conversion error.
     
    Campbell Ritchie
    Marshal
    Posts: 66263
    250
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Look in the Java® Language Specification (=JLS); it tells you that the result of an addition, even short + short, is an int.

    The type of an additive expression on numeric operands is the promoted type of its operands.

    So it can only be assigned to an int or a long, or must be explicitly cast.
     
    I got this tall by not having enough crisco in my diet as a kid. This ad looks like it had plenty of shortening:
    Java file APIs (DOC, XLS, PDF, and many more)
    https://products.aspose.com/total/java
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!