如果您不知道如何实现算法,请尝试将其分解为明显正确的函数,每个实现算法的部分。强>
您想要“打印从 1 到 N(用户输入)的所有数字,但同时可被 3 和 7 整除的数字除外。”老前辈可以使用逻辑运算符快速吐出正确且高效的实现。作为初学者,您可能会发现将其分解成碎片会有所帮助。
// write out the highest level problem to solve, using functions as
// placeholders for part of the algorithm you don't immediately know
// how to solve
for ($x = 1; $x <= $N; $x++) {
if (is_not_divisible_by_3_and_7($x)) {
print "$x\n";
}
}
// then think about the function placeholders, writing them out using
// (again) function placeholders for things you don't immediately know
// how to do
function is_not_divisible_by_3_and_7($number) {
if (is_divisible_by_3_and_7($number)) {
return false;
} else {
return true;
}
}
// keep repeating this...
function is_divisible_by_3_and_7($number) {
if (is_divisible_by_3($number) && is_divisible_by_7($number)) {
return true;
} else {
return false;
}
}
// until you have the simplest possible functions
function is_divisible_by_3($number) {
if ($number % 3 === 0) {
return true;
} else {
return false;
}
}
function is_divisible_by_7($number) {
if ($number % 7 === 0) {
return true;
} else {
return false;
}
}
这更容易理解,因为每个函数都做一件事,而函数名准确地描述了那一件事。这也满足了编程的第一条规则:正确的代码在前。
然后您可以开始考虑让代码变得更好,其中更好意味着:
在上面的代码中采用这种方法,一个明显的改进是将is_divisible_by_3 和is_divisible_by_7 替换为通用函数:
function is_divisible_by_n($number, $divisor) {
if ($number % $divisor === 0) {
return true;
} else {
return false;
}
}
然后,您可以将所有大而笨重的 if x return true else return false 替换为三元运算符,这样您就可以:
function is_divisible_by_n($number, $divisor) {
return ($number % $divisor === 0) ? true : false;
}
function is_divisible_by_3_and_7($number) {
return (is_divisible_by_n($number, 3) && is_divisible_by_n($number, 7)) ? true : false;
}
function is_not_divisible_by_3_and_7($number) {
return (is_divisible_by_3_and_7($number)) ? false : true;
}
现在,请注意 is_not_divisible_by_3_and_7 看起来与 is_divisible_by_3_and_7 完全一样,只是切换了返回值,因此您可以将它们合并为一个方法:
function is_not_divisible_by_3_and_7($number) {
// look how it changed here ----------------------------------------------VVVVV - VVVV
return (is_divisible_by_n($number, 3) && is_divisible_by_n($number, 7)) ? false : true;
}
现在,您可以利用比较本身返回值这一事实,而不是使用三元运算符:
function is_divisible_by_n($number, $divisor) {
// this expression returns a "truthy" value: true or false
// vvvvvvvvvvvvvvvvvvvvvvvvvv
return ($number % $divisor === 0);
}
function is_not_divisible_by_3_and_7($number) {
// also returns a truthy value, but inverted because of the !
// vvv
return ! (is_divisible_by_n($number, 3) && is_divisible_by_n($number, 7));
}
最后,您可以机械地将函数调用替换为等效的逻辑操作:
for ($x = 1; $x <= $N; $x++) {
// all I did below was copy from the function, replace variable names
// v vvvvvvvvvvvvvv vvvvvvvvvvvvvv
if (! (($x % 3 === 0) && ($x % 7 === 0))) {
print "$x\n";
}
}
作为奖励积分,您可以应用 DeMorgan 规则,通过表达式分配 not:
for ($x = 1; $x <= $N; $x++) {
if ($x % 3 !== 0 || $x % 7 !== 0) {
print "$x\n";
}
}
此外,您可能会观察到两个互质数具有公因数当且仅当它们的公因数为 N 乘以 M,所以:
for ($x = 1; $x <= $N; $x++) {
if ($x % (3*7) !== 0) {
print "$x\n";
}
}
您可以通过使用您的语言的功能来进一步压缩表达式:
array_walk(
range(1, $N),
function ($x) {
if ($x % 21 !== 0) print "$x\n";
}
);
等等。关键是你首先要让你的代码正确,然后再让它变得更好。有时,使代码正确意味着要长期努力地思考。有时它只是意味着用非常小的、非常明确的步骤写出来。