将while循环转换为数学公式

Hei*_*fer -1 c c++ iteration math loops

我将循环作为内循环,并试图通过将其转换为数学公式来摆脱它:

while(!(((aux = a * b) <= c) && (c >= aux + d))) --a;
Run Code Online (Sandbox Code Playgroud)

a,b,c,daux都是类型size_t,即unsigned int

注意: a在循环体内的每次迭代中递减!

我完全坚持这个问题.我试图简化循环条件,但由于unsignedness约束而失败.

至于结果,我只是想获得的价值a取决于b,c,d.

Zet*_*eta 5

更换auxa*b在每一个点,你会得到:

    !(a * b <= c && c - a * b >= d)
<=> !(a * b <= c && c >= d + a * b)
<=> !(a * b <= c && d + a * b <= c)
Run Code Online (Sandbox Code Playgroud)

如果d大于c,则第二个条件将为false,因此循环将永远不会终止.所以我们只能考虑d <= c.第二个条件更严格,所以我们可以只关注它:

<=> !(d + a * b <= c)
<=> !(    a * b <= c - d)
<=> !(    a     <= (c - d)/b) // if integer division is used
<=>  (    a     >  (c - d)/b)
Run Code Online (Sandbox Code Playgroud)

鉴于你只是递减a,它要么需要(a <= (c - d)/b)从一开始就满足条件,要么小于或等于(c - d)/b.总的来说我们得到

a = std::min(a, (c - d)/b);
Run Code Online (Sandbox Code Playgroud)


Bar*_*rry 5

让我们简化一下:

while(!(((aux = a * b) <= c) && (c - aux >= d))) --a;
Run Code Online (Sandbox Code Playgroud)

下降aux有利于刚a*b:

while(!((a*b <= c) && (c - a*b >= d))) --a;
Run Code Online (Sandbox Code Playgroud)

改写!(x && y)!x || !y:

while ((a*b > c) || (c - a*b < d)) --a;
Run Code Online (Sandbox Code Playgroud)

翻转第二个表达式上的符号:

while ((a*b > c) || (a*b > c - d)) --a;
Run Code Online (Sandbox Code Playgroud)

这只是:

while (a*b > min(c, c-d)) --a;
Run Code Online (Sandbox Code Playgroud)

也就是说,找到最小的a那样a*b <= min(c, c-d).除非它已经小于那个.所以:

a = min(a, min(c, c-d) / b);
Run Code Online (Sandbox Code Playgroud)

呃,鉴于所有变量unsigned显然是min(c, c-d) == c - d这样的:

a = min(a, (c-d)/b);
Run Code Online (Sandbox Code Playgroud)