仔细检查您的延续条件(其中n 是某个任意整数,在每次使用中可能不同,例如a != 3n 仅表示a 不是三的倍数)。我将展示这个过程:
while((a % 3 != 0 || a % 2 != 0) && (b % 2 != 0 || b % 3 != 0))
( a != 3n OR a != 2n ) AND ( b != 2n OR b != 3n )
( a != 6n ) AND ( b != 6n )
它说:当a 不是两个和三个的倍数时继续,和 b 不是两个和三个的倍数。换句话说,它只会在a 和b 都是六的倍数时继续。另一方面,如果a 或 b 不是六的倍数,它当然会退出。
由于13 的输入值设置了a = 6 和b = 7,因此在第一次迭代时延续情况为假(七不是六的倍数)。
也许最好重新考虑确定某些数字组合是否有效的方式(a)。例如(假设数字必须介于 1 和 N - 1 之间,否则,您的解决方案空间可能是无限的),您可以使用类似:
#include <iostream>
int main() {
// Get the number.
int num;
std::cout << "Number? ";
std::cin >> num;
// Check all i + j = n for 1 <= i,j < n.
for (int i = 1, j = num - 1; i < j; ++i, --j) {
// Disregard if either number not a multiple of 2 or 3.
if ((i % 2) != 0 && (i % 3) != 0) continue;
if ((j % 2) != 0 && (j % 3) != 0) continue;
std::cout << num << " => " << i << ", " << j << "\n";
return 0;
}
std::cout << num << " => no solution\n";
return 0;
}
注意我对i < j 的使用是for 延续条件,这是假设它们必须是不同的 数字。如果允许它们是相同的号码,请将其更改为i <= j。
(a) 使用所有and、or 和not(甚至隐含地,通过反转继续和退出条件),是由于 De Morgan 的定理往往会发挥作用,因此有时麻烦多于其价值:
_____ _ _
A ∩ B ⇔ A ∪ B : (not(A and B)) is ((not A) or (not B))
_____ _ _
A ∪ B ⇔ A ∩ B : (not(A or B)) is ((not A) and (not B))
在这种情况下,如果您拆分单独的检查,代码会变得更具可读性。
有趣的是,如果您使用相当多的输入值运行该代码,您会看到这样的模式:如果存在解决方案,则该解决方案中的一个数字始终是二或三。
那是因为,除了总和小于 5(或小于 4,如果允许解决方案具有相同的数字)的病理情况:
- 每个偶数
2n, n > 1 是2 和2n - 2 之和,两者都是2 的倍数(2n - 2 = 2(n - 1));和
- 每个奇数
2n + 1, n > 2 是 3 和 2n + 1 - 3 的总和,第一个是三的倍数,第二个是二的倍数 (2n + 1 - 3 = 2n - 2 = 2(n - 1))。
所以,实际上,不需要循环:
if (num < 5) { // 4 if allowing duplicates.
std::cout << num << " => no solution\n";
} else {
int first = (num % 2) == 0 ? 2 : 3;
std::cout << num << " => " << first << ", " << (num - first) << "\n";
}
这实际上对某些数字给出了不同的结果,例如17 = 2 + 15 = 3 + 14,但两种解决方案仍然正确。