• 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 Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • paul wheaton
  • Jeanne Boyarsky
  • Ron McLeod
Sheriffs:
  • Paul Clapham
  • Liutauras Vilda
  • Devaka Cooray
Saloon Keepers:
  • Tim Holloway
  • Roland Mueller
Bartenders:

Overflow and Underflow in Java short and float Types

 
Greenhorn
Posts: 28
Hibernate Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hey everyone,

I have a question regarding the following code snippet:



This is from my study guide, and it mentions that when a value exceeds the range of the short data type, overflow occurs. It states that overflow "wraps around" to the lowest negative value and counts up from there, which seems similar to how modulus arithmetic works. However, I'm confused about how exactly this works.

To fit the number 1921222 into the short range, I understand that we're applying modulus to the number. Here's how I think it's done:

1. The short type can only store values between -32,768 and 32,767.
2. When trying to store 1921222, we compute: 1921222 % 65536 = 52994.
3. Since 52994 is greater than 32,767, it must "wrap around."
4. To bring the value into the valid range, we subtract 65536 (the total possible values for short), resulting in: 52994 - 65536 = -12542.
I’m unsure if this conversion is correct or not, and it’s a bit confusing. Is this the same process applied to other integer literals (without floating-point values)?

Regarding floating-point overflow and underflow, I understand that overflow is typically handled by multiplying by 2, while underflow is addressed by dividing by 2 to fit the values within the range. This can lead to results such as infinity or zero. Therefore, there is no "wrap-around." Could you confirm this for me?

Thanks in advance for your help!
 
Bartender
Posts: 10984
87
Eclipse IDE Firefox Browser MySQL Database VI Editor Java Windows ChatGPT
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Chirayu Gangadkar wrote:2. When trying to store 1921222, we compute: 1921222 % 65536 = 52994.


1921222 % 65536 ==> 20678
 
Chirayu Gangadkar
Greenhorn
Posts: 28
Hibernate Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Carey Brown wrote:

Chirayu Gangadkar wrote:2. When trying to store 1921222, we compute: 1921222 % 65536 = 52994.


1921222 % 65536 ==> 20678



Thank you for noticing! My bad; you got that math equation right. Happy for you! 😊
 
Master Rancher
Posts: 5112
38
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Would truncation work?
 
Marshal
Posts: 80288
433
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I think that shorts and floats should only be used when other API forces you to use them, or in certification exams.

I am not convinced you are seeing overflow or modulus arithmetic. It is a sort of reversed truncation to the rightmost sixteen bits of the binary representation of the number. What you actually have is (short)‍(i & 0xffff). The leftmost sixteen bits of the operand are simply deleted. You can get exactly the same result by doing what Carey showed, viz. i % 0x0001_0000. Since a short is a signed number (two's complement); if the No 15 (leftmost) bit is 1, then you will get overflow to a negative value.
Oxff is 65535 and 0x0001_0000 is 655336[edit 65536 /edit].
Try it on JShell. The second line uses the bitwise AND operator. The third attempt shows overflow to a negative value-

jshell
|  Welcome to JShell -- Version 23.0.1
|  For an introduction type: /help intro

jshell> short s = (short)1921222;
s ==> 20678

jshell> short s = 1921222 & 0xffff;
s ==> 20678

jshell> short s = (short)1941222;
s ==> -24858



In the case of floating point numbers, overflow always produces a result of ±∞ and underflow always produces a result of 0.0. I don't understand the bit about dividing by two, but it doesn't look correct, I am afraid.
 
Chirayu Gangadkar
Greenhorn
Posts: 28
Hibernate Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I coded this on JShell



I didn't understand the math behind getting this number -27450, so I had to search for the answer on Google.

This is what they had been doing to get that answer
1. A short in Java can hold values from -32,768 to 32,767
2. 38,086 is greater than 32,767, so it is out of range for a short
3. To "wrap around", you would do: 38,086 - 65,536 = -27,450



If this is wrong again, I apologize; I think I need a rest. Please do confirm with these steps.
 
Chirayu Gangadkar
Greenhorn
Posts: 28
Hibernate Spring Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:
In the case of floating point numbers, overflow always produces a result of ±∞ and underflow always produces a result of 0.0. I don't understand the bit about dividing by two, but it doesn't look correct, I am afraid.





Output:
Min float value: 1.4E-45
Underflowed float value: 0.0

Later found out: Float.MIN_VALUE does not represent the smallest negative float but instead represents the smallest positive float value.

Could you explain this?
 
Sheriff
Posts: 28371
99
Eclipse IDE Firefox Browser MySQL Database
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Chirayu Gangadkar wrote:Later found out: Float.MIN_VALUE does not represent the smallest negative float but instead represents the smallest positive float value.

Could you explain this?


You seem to be thinking here of "smallest" as meaning "closest to zero". But in your statement, "smallest" uses the < operator to determine when a number is smaller than another number. For example -10 is smaller than -8. Which is a perfectly reasonable way to define "smallest".

Another source of confusion: Integer.MIN_VALUE is -2147483648, which is what you might think of as the "smallest" integer value. The API documentation, though, describes it as the "minimum" integer value, possibly avoiding the issue of what "smallest" means for negative values.

So you aren't wrong. It's just that it isn't useful to have a constant which you can use if you want to use the smallest positive integer value. People are just going to use "1" and be done with it. However it is useful to have a constant for the smallest positive float value, for the use of people who are really into the details of floating-point representations. I'm not sure what the largest float value less than zero is, but presumably it's easy to figure out if you're one of those details people.
 
Master Rancher
Posts: 5122
82
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Your latest calculation explaining (short) 1989121222 looks correct.

For float underflow, there's nothing magic about dividing by two here.  you could also divide be 3 or 5 or whatever.  I guess you need to divide by at least two here, to achieve the effect you want - if you divide by 1.9f it rounds back up to the original Float.MIN_VALUE.  But as long as you divide by 2 or more, then it rounds down to 0, because that's closer than Float.MIN_VALUE - and there are no other possible values of a float, between Float.MIN_VALUE  and zero.
 
Chirayu Gangadkar
Greenhorn
Posts: 28
Hibernate Spring Java
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thank you for the detailed explanation!

I see now that the confusion arises from interpreting "smallest" in different contexts. Using < as the defining operator makes sense in terms of how Integer.MIN_VALUE is described as the "minimum" rather than the "smallest" value, avoiding ambiguity.

For floating-point numbers, knowing the smallest positive non-zero value can be critical in certain domains.

Your point about "the largest float less than zero" is also intriguing, while it's not something I've encountered practically, I can see how it could matter for those working deeply with floating-point precision.

Thanks again for clarifying this! I'll definitely keep the distinction between "minimum" and "smallest" in mind when working with these constants.
 
Saloon Keeper
Posts: 28492
210
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:I think that shorts and floats should only be used when other API forces you to use them, or in certification exams.


Cerification exams are notorious minefields where you have to decode stuff that I'd thrash people for doing in real life.

Short and byte integers have only one advantage over "natural" Java integers and that is in how much RAM they require for storage. Frequently in terms of code size and execution speed, they pay for that size with extra overhead.

Back when I built my first PC and had a whopping 12KB of RAM, short integers made sense. Especially since the hardware register size for that first (Z-80) machine was 16 bits. So for a lot of compilers back then "short" was the norm and "long" was 32 bits.

But the least amount of RAM I've seen a JVM occupy outside of the portable device editions was over 100M.  In the early 1980s, 16M was the maximum total address space size for a top-of-the-line IBM mainframe (including OS data structures, etc.). Which is one reason why no one ever back-ported Java for the old OS/MVS operating system. Which, though obsolete is free to run on the Hercules mainframe emulator for people who are into such things. So who cares about the sizes of a few numbers?

These days the only places you're likely to encounter short integers in Java is when dealing with very large arrays of ints or streaming data from other platforms.

"float" is a bit different. Generally it was the size of a hardware floating-point register and thus the native float instructions handled it optimally. Some machines also had primitives for float double and float extended, but they required extra memory bus cycles to load/store the floating-point registers. I don't worry about the size of float I use for the most part, since even basic float has about 6-7 decimal digits worth of accuracy and in the rare cases where I need more precision, it's often the case that floating-point isn't the best choice anyway. No matter how big the float size, 0.1 cannot be represented precisely, for example.

So, in short, the best format for a numeric type is the "native" size for the machine. Or, in Java's case, the JVM.
 
What are you doing in my house? Get 'em tiny ad!
Smokeless wood heat with a rocket mass heater
https://woodheat.net
reply
    Bookmark Topic Watch Topic
  • New Topic