这个问题适合数学家。它已经在办公室里流传开来,我们想看看谁能想出一个更优化的版本。
(((a+p) <= b) && (a == 0 || a > 1) && (b >= p)) &&
((b - (a + p) == 0) || (b - (a + p) > 1))
编辑: 所有数据都是正整数
编辑: 更好等于更简单
这个问题适合数学家。它已经在办公室里流传开来,我们想看看谁能想出一个更优化的版本。
(((a+p) <= b) && (a == 0 || a > 1) && (b >= p)) &&
((b - (a + p) == 0) || (b - (a + p) > 1))
编辑: 所有数据都是正整数
编辑: 更好等于更简单
这个问题已经在实践中得到了比较舒适的回答,但是我下面提到的一点是我还没有看到别人提出过的。
由于我们被告知假设a>=0,并且第一个条件确保b - (a + p) >= 0,所以括号内的||测试可以转换为对不等式1的测试:
(a + p <= b) && (a != 1) && (b>= p) && (b - a - p != 1)
去掉检查(b>= p)似乎很诱人,这将得到nickf的表达式。 这几乎肯定是正确的实际解决方案。 不幸的是,在能够说它是否安全之前,我们需要更多地了解问题领域。
例如,如果使用C语言和32位无符号整数作为a、b和p的类型,考虑这样一种情况:a = 2^31 + 7,p = 2^31 + 5,b = 13。我们有a > 0,(a + p) = 12 < b,但是b < p。(我使用'^'表示指数运算,而不是C中的按位异或。)
可能您的值不会接近这种溢出问题的范围,但是您应该检查这个假设。如果事实证明这是可能的,请添加一个带有该表达式的注释,解释这一点,以便一些热衷于优化的未来开发者不会轻率地删除(b >= p)的测试。
嗯
((b - (a + p) == 0) || (b - (a + p) > 1))
Would be better writen as:
(b - (a + p) >= 0)
Applying this to the whole string you get:
((a+p) <= b) && (a > 1) && (b >= p)) && (b - (a + p) >= 0)
(a + p) <= b is the same thing as b - (a + p) >= 0
所以你可以摆脱那个离开:
((a+p) <= b) && (a > 1) && (b >= p))
第一次迭代:
bool bool1 = ((a+p) <= b) && (a == 0 || a > 1) && (b >= p);
bool bool2 = (b - (a + p) == 0) || (b - (a + p) > 1);
return bool1 && bool2;
第二次迭代:
int value1 = b - (a + p);
bool bool1 = (value1 >= 0) && (a == 0 || a > 1) && (b >= p);
bool bool2 = (value1 == 0) || (value1 > 1);
return bool1 && bool2;
第三次迭代(全是正数)
int value1 = b - (a + p);
bool bool1 = (value1 >= 0) && (a != 1) && (b >= p);
bool bool2 = (value1 == 0) || (value1 > 1);
return bool1 && bool2;
第四次迭代(全部为正数)
int value2 = b - p;
int value1 = value2 - a;
bool bool1 = (value1 >= 0) && (a != 1) && (b - p >= 0);
bool bool2 = (value1 == 0) || (value1 > 1);
return bool1 && bool2;
第五次迭代:
int value2 = b - p;
int value1 = value2 - a;
bool bool1 = (value1 >= 0) && (a != 1) && (value2 >= 0);
bool bool2 = (value1 == 0) || (value1 > 1);
return bool1 && bool2;
好的,我希望我的数学没错,但如果我是对的,那么这就简化了很多。尽管最终看起来不同,但核心逻辑应该是相同的。
// Initial equation
(((a + p) <= b) && (a == 0 || a > 1) && (b >= p)) && ((b - (a + p) == 0) || (b - (a + p) > 1))
// ((a + p) <= b) iif a = 0 && p = b; therefore, b = p and a = 0 for this to work
(b == p) && ((b - (a + p) == 0) || (b - (a + p) > 1))
// Simplification, assuming that b = p and a = 0
(b == p) && (a == 0)
然而,如果我们假设零既不是正数也不是负数,那么这意味着方程中提供的任何值都将大于或等于一。这反过来又意味着该方程将始终评估为false,因为以下原因:
(a == 0 || a > 1)
只有当 a >= 2 时才会计算为真;但是,如果以下条件也成立:
(b >= p)
((a + p) <= b)
通过替换变成:
((2 + b) <= b)
这显然永远不可能为真。
我将这个作为对nickf答案的评论,但是我想单独把它作为一个答案提供出来。所有好的答案似乎都是他的变体,包括我的。但是既然我们不依赖编译器进行优化(如果OP依赖编译器,我们甚至不会这样做),那么从3个ANDs简化为以下意味着只有2个3个部分需要被评估的值。如果这是在脚本中完成的,与编译代码相比,这将有所不同。
(a != 1) && ((b > (a + p + 1)) || (b == (a + p))))
((a == 0 || a > 1) && ((b-p) > 1) )
(((a+p) <= b) && (a == 0 || a > 1) && (b >= p)) && ((b - (a + p) == 0) || (b - (a + p) > 1))
由于a>=0(正整数),因此术语(a == 0 || a>1)始终为真
如果((a+p) <= b),则当a,b,p >=0时,(b>=p)为真
因此,((a+p) <= b) && (a == 0 || a>1) && (b>=p)) && ((b - (a + p) == 0)简化为
b>=(a+p)
(b - (a + p) == 0) || (b - (a + p) > 1) 等价于 b>=(a+p)
因此整个方程可以简化为
**b>= (a+p)**