忽略休息的有效划分方法

发布于 2024-11-26 08:04:47 字数 479 浏览 3 评论 0原文

我发现有两种方法可以从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

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

there are 2 ways i found to get a whole number from a division in c++

question is which way is more efficient (more speedy)

first way:

Quotient = value1 / value2;  // normal division haveing splitted number

floor(Quotient);             // rounding the number down to the first integer

second way:

Rest = value1 % value2;             // getting the Rest with modulus % operator

Quotient = (value1-Rest) / value2;  // substracting the Rest so the division will match

also please demonstrate how to find out which method is faster

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

不语却知心 2024-12-03 08:04:47

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

Quotient = value1 / value2;

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

如果您有浮点数,那么第二种方法根本不起作用,因为 % 仅为整数定义。但是从实数相除得到整数是什么意思呢? 8.5 除以 3.2 会得到什么整数?问这个问题有意义吗?

附带说明一下,您所说的“休息”通常称为“提醒”。剩余。

If you're dealing with integers, then the usual way is

Quotient = value1 / value2;

That's it. The result is already an integer. No need to use the floor(Quotient); statement. It has no effect anyway. You would want to use Quotient = floor(Quotient); if it was needed.

If you have floating point numbers, then the second method won't work at all, as % is only defined for integers. But what does it mean to get a whole number from a division of real numbers? What integer do you get when you divide 8.5 by 3.2? Does it ever make sense to ask this question?

As a side note, the thing you call 'Rest' is normally called 'reminder'.remainder.

放飞的风筝 2024-12-03 08:04:47

使用此程序:

#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 和不使用 -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 进行编译,您将获得相同的程序集,在该优化级别,两种替代方案是相同的。

Use this program:

#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;
}

You can time execution

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

Or, you look at the assembly output:

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)

As you see, doing only the division is faster.

Edited to fix error in code, formatting and wrong diff.

More edit (explaining the assembly diff): In the second case, when doing the modulus first, the assembly shows that two idivl operations are needed: one to get the result of % and one for the actual division. The above diff shows the subtraction and the second division, as the first one is exactly the same in both codes.

Edit: more relevant timing information:

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

Hope it helps.

Edit: diff between assembly with -O0 and without.

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 

Since the defualt optimization level of gcc is O0 (see this article explaining optimization levels in gcc) the result was expected.

Edit: if you compile with -O3 as one of the comments suggested you'll get the same assembly, at that level of optimization, both alternatives are the same.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文