是否有算法来确定a*b是否符合整数的可能值?(没有铸造更广泛的类型)

Pac*_*ier 9 java language-agnostic algorithm

嗨,我想知道是否有一种方法来实现这种方法,而不会转换为更广泛的数据类型(例如,长,双等)?

CanTimes(int a, int b){
    returns true if a * b is within the range of -2^31 to 2^31-1, else false;
}
Run Code Online (Sandbox Code Playgroud)

例如,我们可以为方法实现一个CanAdd(没有强制转换),如下所示:

    public static boolean CanPlus(int a, int b) {
        if (b >= 0) {
            return a <= Integer.MAX_VALUE - b
        } else {
            return a >= Integer.MIN_VALUE - b
        }
    }
Run Code Online (Sandbox Code Playgroud)

实现语言是Java,当然这更像是与语言无关的问题.

我在想是否有一些逻辑我们可以用来决定a*b是否适合整数的范围而不将其转换为更宽的数据类型?

解决方案 根据Strelok的评论:

public static boolean CanTimes(int a, int b) {
    if (a == 0 || b == 0) {
        return true;
    }
    if (a > 0) {
        if (b > 0) {
            return a <= Integer.MAX_VALUE / b;
        } else {
            return a <= Integer.MIN_VALUE / b;
        }
    } else {
        if (b > 0) {
            return b <= Integer.MIN_VALUE / a;
        } else {
            return a <= -Integer.MAX_VALUE / b;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Str*_*lok 1

根据我的评论,这是改编版本,带有一些单元测试:

public static int mulAndCheck( int a, int b )
{
    int ret;
    String msg = "overflow: multiply";
    if ( a > b )
    {
        // use symmetry to reduce boundry cases
        ret = mulAndCheck( b, a );
    }
    else
    {
        if ( a < 0 )
        {
            if ( b < 0 )
            {
                // check for positive overflow with negative a, negative b
                if ( a >= Integer.MAX_VALUE / b )
                {
                    ret = a * b;
                }
                else
                {
                    throw new ArithmeticException( msg );
                }
            }
            else if ( b > 0 )
            {
                // check for negative overflow with negative a, positive b
                if ( Integer.MIN_VALUE / b <= a )
                {
                    ret = a * b;
                }
                else
                {
                    throw new ArithmeticException( msg );

                }
            }
            else
            {
                // assert b == 0
                ret = 0;
            }
        }
        else if ( a > 0 )
        {
            // assert a > 0
            // assert b > 0

            // check for positive overflow with positive a, positive b
            if ( a <= Integer.MAX_VALUE / b )
            {
                ret = a * b;
            }
            else
            {
                throw new ArithmeticException( msg );
            }
        }
        else
        {
            // assert a == 0
            ret = 0;
        }
    }
    return ret;
}

@Test( expected = ArithmeticException.class )
public void testOverflow()
{
    mulAndCheck( Integer.MAX_VALUE, Integer.MAX_VALUE );
}

@Test( expected = ArithmeticException.class )
public void testOverflow1()
{
    mulAndCheck( Integer.MIN_VALUE, Integer.MAX_VALUE );
}

@Test
public void testTimesMinus1()
{
    Assert.assertEquals( Integer.MIN_VALUE + 1, mulAndCheck( Integer.MAX_VALUE, -1 ) );
    Assert.assertEquals( Integer.MAX_VALUE, mulAndCheck( Integer.MIN_VALUE + 1, -1 ) );
}
Run Code Online (Sandbox Code Playgroud)