PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Thursday, July 21, 2022

[FIXED] How to detect and prevent integer overflow when multiplying an integer by float in Java?

 July 21, 2022     floating-point, integer, integer-overflow, java     No comments   

Issue

I have read this article NUM00-J. Detect or prevent integer overflow and this question How does Java handle integer underflows and overflows and how would you check for it?.

As you can see, there are many solutions to prevent integer overflow when multiplying an integer by an integer. But I wonder is there any solution to prevent integer overflow when multiplying an integer by float?

My current (silly) solution:

public static final int mulInt(int a, float b) {
    double c = a * b;
    return c > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int)c;
}

But it has a lot of problems:

  1. It can get the expected result when multiplying performs multiplication with both parameters having to be small numbers.
  2. When either parameter is large digits the result is bound to be incorrect (I know in part because of the floating-point data type).
  3. Suppose if the result of the calculation is even greater than the maximum value of double, it will be unstoppable and return a negative number.

So, what is the real solution to this problem?

Your answer will be very helpful, I will appreciate it!

UPDATE: There is another question here How can I check if multiplying two numbers in Java will cause an overflow? that is quite similar BUT it is about multiplying an integer by an integer instead of multiplying by a float.


Solution

Below is a C approach that may shed light in Java.

Perform the multiplication using double, not float math before the assginment to gain the extra precision/range of double. Overflow is not then expected.

A compare like c > Integer.MAX_VALUE suffers from Integer.MAX_VALUE first being converted into a double. This may lose precision.*1 Consider what happens if the converted value is Integer.MAX_VALUE + 1.0. Then if c is Integer.MAX_VALUE + 1.0, code will attempt to return (int) (Integer.MAX_VALUE + 1.0) - not good. Better to use well formed limits. (Negative ones too.) In C, maybe Java, floating point conversion to int truncates the fraction. Special care is needed near the edges.

#define INT_MAX_PLUS1_AS_DOUBLE ((INT_MAX/2 + 1)*2.0)

int mulInt(int a, float b) {
  // double c = a * b;
  double c = (double) a * b;
  
  //return c > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int)c;
  if (c < INT_MAX_PLUS1_AS_DOUBLE && c - INT_MIN > -1.0) {
    return (int) c;
  } 
  if (c > 0) return INT_MAX;
  if (c < 0) return INT_MIN;
  return 0; // `b` was a NaN
}

c - INT_MIN > -1 is like c > INT_MIN - 1, but as INT_MIN is a -power-of-2, INT_MIN - 1 might not convert precisely to double. c - INT_MIN is expected to be exact near the edge cases.


*1 When int is 32-bit (or less) and double is 64-bit (with 53-bit significant) not an issue. But important with wider integer types.



Answered By - chux - Reinstate Monica
Answer Checked By - Timothy Miller (PHPFixing Admin)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing