Jon*_*ood 22
想法是来自/和%的结果可以从处理器上的单个DIV指令确定.因此,从历史上看,div()用于提供获得两者的优化方法.
但是,我发现新的编译器能够将/和%运算优化为单个除法.例如,我在Microsoft Visual C++上看到了这种优化.在这些情况下,div()实际上不提供优势,事实上,如果涉及呼叫,甚至可能会很慢.
如果你想同时计算商和余数,那应该比使用/和%运算符更快.
简短的回答:在现代环境中并非如此。
人们已经解释了为什么收益div很弱甚至不存在。
实际上更糟糕:div朋友们引入了类型耦合,这损害了良好的实践(请参阅下面的缺点部分)。
正如其他答案中所述,调用div而不是/and%最有可能确保该操作仅在程序集级别完成一次。
但在大多数现代环境中:
div(如果有的话)通常可以忽略不计。/现代%编译器时,无论如何,通过仅生成一个除法指令来获取商和余数,也可以做正确的事情。=> 没有实际好处div。如果数字的确切类型(例如int或long)是静态已知的(也就是说,您的代码始终显式使用 int 或 long),则使用divforint和ldivfor long 是可以的。
但是,如果您遵循小部分编程的良好实践,避免不必要的假设,您很快就会意识到使用div并将ldiv代码分别与类型int或联系起来long。相反,/并且%会自动调整到当前情况下实际使用的任何类型,从而保持代码简洁。
这在两种情况下尤其明显:
typedef抽象实际类型——div即使在 C 中也是笨拙的!div打败了模板。下面的示例显示,使用 '/' 和 '%' 的代码干净、简单,并且与 int、long、long long 或其他任何东西无关,而使用divand 的代码则变得笨拙。
Testing with int
my_math_func_div_WRONG says 6
my_math_func_OVERKILL says 6 // Works but overkill cast to long
my_math_func_GOOD says 6 // No div no headache.
Testing with int in long type
my_math_func_div_WRONG says 6
my_math_func_OVERKILL says 6 // Works but overkill cast to long
my_math_func_GOOD says 6 // No div no headache.
Testing with actual long
my_math_func_div_WRONG says 70503280 // FAIL
my_math_func_OVERKILL says 500000006
my_math_func_GOOD says 500000006 // No div no headache.
Run Code Online (Sandbox Code Playgroud)
源代码:
#include <iostream>
// '/' and '%' are smart about type.
// This code is simple and will work with int, long, longlong, char, whatever.
template<typename T>
T my_math_func_GOOD( T number )
{
T quotient = number / 10;
T remainder = number % 10;
// do something
return quotient + remainder;
}
// div and friends are not smart about type.
// How do you write code smart about type with them ?
// Plus adds dependency on C's stdlib.
#include <stdlib.h>
template<typename T>
T my_math_func_div_WRONG( T number )
{
// This will always downcast to int. Defeats purpose of template.
div_t result = div( number, 10 );
T quotient = result.quot;
T remainder = result.rem;
// do something
return quotient + remainder;
}
template<typename T>
T my_math_func_OVERKILL( T number )
{
// This will always cast to long (up from int, OVERKILL, possibly down from long long, FAIL). Defeats purpose of template.
ldiv_t result = ldiv( number, 10 );
T quotient = result.quot;
T remainder = result.rem;
// do something
return quotient + remainder;
}
template<typename T>
void my_math_func_test( T number )
{
T n;
n = my_math_func_div_WRONG( number );
std::cout << "my_math_func_div_WRONG\tsays " << n << std::endl; // writes 6
n = my_math_func_OVERKILL( number );
std::cout << "my_math_func_OVERKILL\tsays " << n << std::endl; // writes 6
n = my_math_func_GOOD( number );
std::cout << "my_math_func_GOOD\tsays " << n << std::endl; // writes 6
}
// C99 allows absence of int argc, char **argv
int main()
{
std::cout << std::endl << "Testing with int" << std::endl;
my_math_func_test<int>( 42 );
std::cout << std::endl << "Testing with int in long type" << std::endl;
my_math_func_test<long>( 42 );
std::cout << std::endl << "Testing with actual long" << std::endl;
my_math_func_test<long>( 5000000042 );
// std::cout << std::endl << "Testing with long long" << std::endl;
// my_math_func_test<long long>( 50000000000000000042 );
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3412 次 |
| 最近记录: |