数学通常应该用于其他函数/语句吗
Should Maths Generally Be Used Over Other Functions/ Statements
在我最近的一些程序中,我一直在使用基本微积分来替换 if
语句,例如在我使用的 for
循环中:
pos = cbltSz*(x-1)
获取小立方体相对于大立方体的位置,而不是像 if(x == 0){pos = -cbltSz}
这样说。这或多或少是为了稍微整理一下代码。但这让我开始思考。使用数学会在多大程度上优于预定义的语句/函数?不同语言的差异有多大?这是假设我的数学使用 比审美以外的替代方法更可取。
请注意,如果 x
不为零,则您的语句 pos = cbltSz*(x-1)
和 if(x == 0){pos = -cbltSz}
不等价:第一个将 pos
设置为某个确定值,而第二个离开它到它以前的值。这种差异的重要性取决于程序的其余部分。这两个陈述在清晰度上也有所不同——第二个陈述更好地表达了你的目的,而第一个陈述 not "neaten up the code a little bit"。在大多数程序中,提高清晰度比稍微提高速度更重要。
所以您的问题的答案取决于太多因素,无法在此处获得完整答案。
现代 CPU 具有很深的流水线,因此分支预测错误可能会对性能产生相当大的影响。另一方面,它们往往具有相当大的浮点计算能力,通常能够在不同的 ALU 上并行执行多个浮点运算。因此,这种方法可能具有性能优势。但这一切都取决于。如果应用程序已经在进行大量的数字运算,则 ALU 可能会饱和。如果分支预测器做得很好,分支预测错误在许多应用程序中可能很少见。
所以我会遵循通常的优化规则:不要尝试手动优化所有内容。不要以可读性和可维护性为代价进行优化。如果您遇到性能瓶颈,请确定代码库的热点部分并考虑这些部分的替代方案。在基准测试中尝试替代方案,因为理论上的考虑只能让你走到这一步。
大多数早期的编程语言设计者不明白,而且许多人仍然不明白的是,数学函数与用户定义的函数有点不同。如果我们做过任何三角运算,我们都知道 sin(PI/8) 的意思,我们很乐意将 class 嵌入
等表达式中
rx = cos(theta) * x - sin(theta) * y;
但是你自己写的函数很少像基本的数学函数。他们有几个参数,他们 return 几个参数,通常不太清楚他们做了什么。您最不想要的就是将它们嵌入复杂的表达式中。
其次,数学有自己的符号系统是有原因的。一旦表达式超过某个低复杂度,编程语言的精简、纯 ascii 系统就会崩溃。 (我使用三个规则,三层嵌套括号是您的用户可以接受的所有内容)。而且,如果没有特殊的编程支持,编程功能就无法逃脱它们的领域。
pow(sqrt(-1), sqrt(-1));
除非你安装了一个复杂的数学库,否则不会做你想做的事。
至于性能,一些 Fortran 和 C 编译器非常积极地优化数学例程,不断传播等。其他人不会。这取决于。
在我最近的一些程序中,我一直在使用基本微积分来替换 if
语句,例如在我使用的 for
循环中:
pos = cbltSz*(x-1)
获取小立方体相对于大立方体的位置,而不是像 if(x == 0){pos = -cbltSz}
这样说。这或多或少是为了稍微整理一下代码。但这让我开始思考。使用数学会在多大程度上优于预定义的语句/函数?不同语言的差异有多大?这是假设我的数学使用 比审美以外的替代方法更可取。
请注意,如果 x
不为零,则您的语句 pos = cbltSz*(x-1)
和 if(x == 0){pos = -cbltSz}
不等价:第一个将 pos
设置为某个确定值,而第二个离开它到它以前的值。这种差异的重要性取决于程序的其余部分。这两个陈述在清晰度上也有所不同——第二个陈述更好地表达了你的目的,而第一个陈述 not "neaten up the code a little bit"。在大多数程序中,提高清晰度比稍微提高速度更重要。
所以您的问题的答案取决于太多因素,无法在此处获得完整答案。
现代 CPU 具有很深的流水线,因此分支预测错误可能会对性能产生相当大的影响。另一方面,它们往往具有相当大的浮点计算能力,通常能够在不同的 ALU 上并行执行多个浮点运算。因此,这种方法可能具有性能优势。但这一切都取决于。如果应用程序已经在进行大量的数字运算,则 ALU 可能会饱和。如果分支预测器做得很好,分支预测错误在许多应用程序中可能很少见。
所以我会遵循通常的优化规则:不要尝试手动优化所有内容。不要以可读性和可维护性为代价进行优化。如果您遇到性能瓶颈,请确定代码库的热点部分并考虑这些部分的替代方案。在基准测试中尝试替代方案,因为理论上的考虑只能让你走到这一步。
大多数早期的编程语言设计者不明白,而且许多人仍然不明白的是,数学函数与用户定义的函数有点不同。如果我们做过任何三角运算,我们都知道 sin(PI/8) 的意思,我们很乐意将 class 嵌入
等表达式中 rx = cos(theta) * x - sin(theta) * y;
但是你自己写的函数很少像基本的数学函数。他们有几个参数,他们 return 几个参数,通常不太清楚他们做了什么。您最不想要的就是将它们嵌入复杂的表达式中。
其次,数学有自己的符号系统是有原因的。一旦表达式超过某个低复杂度,编程语言的精简、纯 ascii 系统就会崩溃。 (我使用三个规则,三层嵌套括号是您的用户可以接受的所有内容)。而且,如果没有特殊的编程支持,编程功能就无法逃脱它们的领域。
pow(sqrt(-1), sqrt(-1));
除非你安装了一个复杂的数学库,否则不会做你想做的事。
至于性能,一些 Fortran 和 C 编译器非常积极地优化数学例程,不断传播等。其他人不会。这取决于。