你能简化这个表达式吗?

25

这个问题适合数学家。它已经在办公室里流传开来,我们想看看谁能想出一个更优化的版本。

(((a+p) <= b) && (a == 0 || a > 1) && (b >= p)) && 
    ((b - (a + p) == 0) || (b - (a + p) > 1))

编辑: 所有数据都是正整数

编辑: 更好等于更简单


变量有什么限制吗?例如整数类型、隐式int->bool转换等等? - mkoeller
1
亚当,你现在可能要对数百个工作小时的损失负责了,哈哈。 - PEZ
很高兴你们都在帮忙!我会运行其中一些并发布我的结果。 - Adam Naylor
那么你打算发布你们办公室得出的答案是什么,对吗? - rjzii
2
只是想推荐一下:http://codegolf.stackexchange.com/ 我认为这个问题更适合在那里提问 :) - The Unfun Cat
显示剩余7条评论
27个回答

0

这个问题已经在实践中得到了比较舒适的回答,但是我下面提到的一点是我还没有看到别人提出过的。

由于我们被告知假设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)的测试。


a是一个正整数,这意味着a>0而不是a>=0。 - Steven A. Lowe

0

((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)) 

不!((b - (a + p) == 0) || (b - (a + p) > 1)) 不等于 (b - (a + p) >= 0) !!! 正确的简化应该是:(b - (a + p) != 1)。 - Brian Genisio
a 等于 0,所以 a 大于 1 不足以满足条件。 - Adam Naylor

0

第一次迭代:

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;

这是我见过的第一个实际可行的版本,但很难称之为简化... - nickf
简化是为了谁?是为了编译器还是为了人类?对于编译器来说,没有必要。对于人类来说,只需要使用有意义的名称而不是value1和value2。 - Andrea Francia

0

好的,我希望我的数学没错,但如果我是对的,那么这就简化了很多。尽管最终看起来不同,但核心逻辑应该是相同的。

// 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)

那意味着p至少等于b,因此:
((a + p) <= b)

通过替换变成:

((2 + b) <= b)

这显然永远不可能为真。


b - (a + p) >= 0)。这是不正确的;b - (a + p) 不能等于1。 - Ali Ersöz
你为什么在“(a == 0 || a > 1)”语句中逃避了“a>1”的部分? - Ali Ersöz
@yapiskan - 如果我假设当(b = p)且(a = 0)时((a + p) <= b),那么就没有必要检查是否(a > 1),因为方程式将允许((a + b) <= b),其中(a > 1),这显然是错误的。 - rjzii

0

我将这个作为对nickf答案的评论,但是我想单独把它作为一个答案提供出来。所有好的答案似乎都是他的变体,包括我的。但是既然我们不依赖编译器进行优化(如果OP依赖编译器,我们甚至不会这样做),那么从3个ANDs简化为以下意味着只有2个3个部分需要被评估的值。如果这是在脚本中完成的,与编译代码相比,这将有所不同。

(a != 1) && ((b > (a + p + 1)) || (b == (a + p))))

基于一条评论,我将添加这个与AND版本相比更好的部分:
我想这取决于您的真实结果数据集是否大于输入集的50%。输入越频繁为True,我的变化就越好。因此,使用这个方程式,看起来AND样式会更好(至少对于我的0-500个输入数据集)。

脚本会有条件地处理 && 的情况,例如如果是 A && B && C,它将在其中一个条件为假时停止处理。替换为 || 只意味着如果第一个条件为假或其中一个 || 条件为真,它将停止处理。不确定这如何改进。 - frankodwyer
好观点。我猜这取决于您的真实结果数据集是否大于输入集的50%。输入越频繁,我的变化就会越好。因此,根据这个方程式,看起来AND样式会更好(至少对于我的0-500个输入数据集)。 - shank

0
以下逻辑怎么样,请发表评论:
((a == 0 || a > 1) && ((b-p) > 1) )

-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)**

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接