Check if Integer is too great

2019-07-11 15:49发布

问题:

I am working on an exchange system and the user is setting the price and amount for an exchange.

I want to make sure that the exchange is no greater than the Integer maximum value, but I am running into a problem.

When the amount of the exchange is put to 9 or more, even though I have a check to make sure the number is no greater than the maximum value, it does not work. I have done some debugging and when setting the amount to 9 while the price is 2,147,483,646 (1 less than the max number), it prints out this:

2,147,483,630 - 9

This is my debugging code, what should I add to it to make sure that this does not happen?

public void setPrimaryAmount(int primaryAmount) {
        int price = primaryAmount * this.price;
        System.out.println(Misc.format(this.price * primaryAmount) + " - " + primaryAmount);
        if (price > Integer.MAX_VALUE ||
                price == Integer.MAX_VALUE ||
                price >= Integer.MAX_VALUE ||
                price < 0 || price <= 0 ||
                price++ == Integer.MAX_VALUE) {
            System.out.println("Attempted to set a bad amount.");
            return;
        }
        this.primaryAmount = primaryAmount;
    }

"Attempted to set a bad amount" prints out until you enter an amount >= 9.

回答1:

You can't store a value in an int, and then check to see whether it's too big for an int. Store it in a long instead.

long price = (long)primaryAmount * (long)this.price;


回答2:

In Java 8, one approach would be to use

Math.addExact(int, int);

which according to Javadocs will throw an ArithmeticException if the result overflows an int. In other versions, I would recommend what Flight Odyssey suggested and use longs at least for these types of checks.



回答3:

When setting 'price' to primaryAmount * this.price to check if it is above Integer.MAX_VALUE or below Integer.MIN_VALUE, because it is an integer it will roll, for example, a value of Integer.MAX_VALUE += 1 will become Integer.MIN_VALUE and vice-versa therefore checking is not not needed. You could of course make it a bigger data type and then check but there is a faster way. As long as we know what this.price is we can determine what the maximum value 'primaryAmount' can be without exeeding 2,147,483,646 once multiplied with this.price simply by doing it backwards:

int max = 2147483646 / this.price

This value could act as a max for a simple trim function to ensure it is within range, e.g:

private int confirmRange(int number, int max, int min) {
    if (number > max) number = max;
    if (number < min) number = min;
    return number;
}