有效划分忽略休息的方法

efficient way to divide ignoring rest

本文关键字:方法 划分 有效      更新时间:2023-10-16

我发现有 2 种方法可以从 C++ 中的除法中获取整数

问题是哪种方式更有效(更快(

第一种方式:

Quotient = value1 / value2;  // normal division haveing splitted number
floor(Quotient);             // rounding the number down to the first integer

第二种方式:

Rest = value1 % value2;             // getting the Rest with modulus % operator
Quotient = (value1-Rest) / value2;  // substracting the Rest so the division will match

还请演示如何找出哪种方法更快

如果你正在处理整数,那么通常的方法是

Quotient = value1 / value2;

就是这样。结果已经是一个整数。无需使用 floor(Quotient); 语句。反正也没效果。如果需要,您可能希望使用Quotient = floor(Quotient);

如果您有浮点数,则第二种方法根本不起作用,因为%仅为整数定义。但是从实数的除法中得到整数意味着什么?当你把 8.5 除以 3.2 时,你会得到什么整数?问这个问题有意义吗?

作为旁注,您称为"休息"的东西通常称为"提醒"。剩余。

使用此程序:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#ifdef DIV_BY_DIV
#define DIV(a, b) ((a) / (b))
#else
#define DIV(a, b) (((a) - ((a) % (b))) / (b))
#endif
#ifndef ITERS
#define ITERS 1000
#endif
int main()
{
    int i, a, b;
    srand(time(NULL));
    a = rand();
    b = rand();
    for (i = 0; i < ITERS; i++)
        a = DIV(a, b);
    return 0;
}

您可以定时执行

mihai@keldon:/tmp$ gcc -Wall -Wextra -DITERS=1000000 -DDIV_BY_DIV 1.c && time ./a.out 
real    0m0.010s
user    0m0.012s
sys     0m0.000s
mihai@keldon:/tmp$ gcc -Wall -Wextra -DITERS=1000000 1.c && time ./a.out 
real    0m0.019s
user    0m0.020s
sys     0m0.000s

或者,您查看程序集输出:

mihai@keldon:/tmp$ gcc -Wall -Wextra -DITERS=1000000 -DDIV_BY_DIV 1.c -S; mv 1.s 1_div.s 
mihai@keldon:/tmp$ gcc -Wall -Wextra -DITERS=1000000 1.c -S; mv 1.s 1_modulus.s 
mihai@keldon:/tmp$ diff 1_div.s 1_modulus.s 
24a25,32
>   movl    %edx, %eax
>   movl    24(%esp), %edx
>   movl    %edx, %ecx
>   subl    %eax, %ecx
>   movl    %ecx, %eax
>   movl    %eax, %edx
>   sarl    $31, %edx
>   idivl   20(%esp)

如您所见,只做除法会更快。

经过编辑以修复代码,格式和错误差异中的错误。

更多编辑(解释程序集差异(:在第二种情况下,当首先进行模量时,程序集显示需要两个idivl操作:一个用于获得%的结果,另一个用于实际除法。上面的差异显示了减法和二除法,因为第一个在两个代码中完全相同。

编辑:更多相关的时间信息:

mihai@keldon:/tmp$ gcc -Wall -Wextra -DITERS=42000000 -DDIV_BY_DIV 1.c && time ./a.out 
real    0m0.384s
user    0m0.360s
sys     0m0.004s
mihai@keldon:/tmp$ gcc -Wall -Wextra -DITERS=42000000 1.c && time ./a.out 
real    0m0.706s
user    0m0.696s
sys     0m0.004s

希望对您有所帮助。

编辑:带-O0和不带的程序集之间的差异。

mihai@keldon:/tmp$ gcc -Wall -Wextra -DITERS=1000000 1.c -S -O0; mv 1.s O0.s
mihai@keldon:/tmp$ gcc -Wall -Wextra -DITERS=1000000 1.c -S; mv 1.s noO.s
mihai@keldon:/tmp$ diff noO.s O0.s 

由于gcc的定优化级别是O0(请参阅本文gcc解释优化级别(,因此结果是意料之中的。

编辑:如果您按照其中一个注释建议使用-O3进行编译,您将获得相同的程序集,在该优化级别,两种选择是相同的。