【问题标题】:Which is more efficient to use in a for loop, i<sqrt(n) or i*i<(n)?在 for 循环中使用 i<sqrt(n) 还是 i*i<(n) 哪个更有效?
【发布时间】:2020-03-26 06:55:09
【问题描述】:

谁能帮我看看以下两个哪个更有效更正确?

1.

for(int i = num; i * i <= n; i++)

2.

int root = sqrt(n);
for(int i = num; i <= root; i++)

在第一种方法中,我们在每次循环运行时计算 i 的平方。此外,我们无法预先计算 i 的平方,因为 i 每次都会更新。

在第二种方法中,我们不是每次都计算 sqrt(n)。这样可以节省时间吗?

即使对于大数字(如 10^6),第二个循环是否会更快地工作并获得 100% 准确的结果?

【问题讨论】:

  • 乘法很便宜。但这确实需要基准测试,正如您所指出的,取决于n
  • *sqrt 快。对于某些数字,两者都不精确。
  • * 对于 integers 是不精确的?这种循环常用于素数搜索
  • @Jean-FrançoisFabre:用词错误。整数无法处理大数字。浮点数会丢失具有大量数字的数字的精度。 Bigint 很慢,在 C 中需要一个库。选择你的毒药。
  • 是的,我对 python 更习惯了。对于 C,使用整数是一个很大的烦恼。但是对于素数搜索,您不能做任何其他事情(uint64_t 有点帮助)。在某些时候,您将不得不使用一些大整数库。是的,它很慢。为什么你认为最大的已知素数只有 2**82,589,933-1(也是梅森素数)? :)

标签: c time-complexity c++14 square primality-test


【解决方案1】:

第二种情况应该更有效,因为不需要为循环中的每次迭代计算循环限制器。尝试使用下面给出的代码测量通过 2 种类型的 for 循环所使用的 CPU 时间。 对于较小的数字(例如 n = 25),对于第一种情况,看起来 cpu 时间实际上更短。但是对于 n>=100 的值,第二种情况会提供更短的 cpu 时间。

    clock_t start,end;
    double cpu_time_used;
    double n, root;

    n = atoi(argv[1]);
    printf("n= %0f \n",n);
    start = clock();
    for (int i=0; i*i<n; i++);
    end = clock();
    cpu_time_used = ((double) (end-start)) / CLOCKS_PER_SEC;
    printf("first iter: cpu_time_used: %f \n", cpu_time_used);

    start = clock();
    root = sqrt(n);
    for (int i=0; i<=root; i++);
    end = clock();
    cpu_time_used = ((double) (end-start)) / CLOCKS_PER_SEC;
    printf("second iter: cpu_time_used: %f \n", cpu_time_used);

输出:

n= 25.000000 
first iter: cpu_time_used: 0.000004 
second iter: cpu_time_used: 0.000011 

n= 100.000000 
first iter: cpu_time_used: 0.000002 
second iter: cpu_time_used: 0.000001 

n= 1000000.000000 
first iter: cpu_time_used: 0.000011 
second iter: cpu_time_used: 0.000008 

【讨论】:

  • 您对 n=100 比 n=25 快的事实有任何疑问吗?
  • 因为for 循环完全没有做任何事情,编译器可能已经丢弃了它们。所以你可能没有测量你认为你正在测量的东西。 (稍微温和的反汇编会告诉你编译器产生了什么。)在我的机器上CLOCKS_PER_SEC 是 100 万条,但它可以轻松地在一微秒内撕掉几千条指令,尽管可能只有一千条指令——所以尝试在我的机器上,使用clock() 测量 25 或 100 次乘法的运行时间会有点棘手。
猜你喜欢
  • 2020-10-12
  • 1970-01-01
  • 2010-10-08
  • 2021-06-09
  • 2013-04-24
  • 1970-01-01
  • 2013-04-23
  • 2020-12-28
  • 2019-07-13
相关资源
最近更新 更多