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)
根据我的评论,这是改编版本,带有一些单元测试:
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)