检查整数是否为0的最佳方法

时间:2013-07-01 03:19:56

标签: optimization language-agnostic

检查整数中是否 0 (零)的最佳方法是什么

例如:

505 -> True
555 -> False
44444032 -> True
0000 -> True

我试过这个

public bool has0(int no)
{
    if(no==0)return true;
    while(no!=0)
    {
        if(no%10==0)return true;
        no=no/10;
    }
    return false;
}

这很有效,但考虑到我需要在大数字上特别称这种方法 10亿次,这需要特别花费大量时间

for(int i=0;i<1000000000;i++)has0(i);

那么,通过使用|&^或其他任何方式使用某些位级运算符来检查数字中是否存在0的最佳方法是什么。

谢谢..

4 个答案:

答案 0 :(得分:8)

模数是一种昂贵的整数运算(类似于整数除法)。您可以通过查看数字是否均匀来消除测试中一半可能的答案。没有奇数的模10等于零。

if(((no&amp; 0x1)== 0x00)&amp;&amp;((no%10)== 0))   return true;

你会在偶数上付出更多,但在奇数上却少得多。因此,如果它是所有偶数,这将无济于事(它实际上会受到伤害),但如果它是50/50甚至20/80(20%奇数),你可能仍会领先。

此外,整数乘法更便宜,因此您可以先进行除法并计算模10。

while (no)
{
  if (no & 0x1))  // odd?
    no /= 10;
  else  // even
  {
    int nNext = no / 10;  // just do integer divide, and calculate modulo in next line
    if ((no - (10 * nNext)) == 0)  // replaces "more expensive" modulo operation with integer multiply and subtraction
      return true;
    no = nNext;
  }
}

答案 1 :(得分:4)

虽然接受的答案肯定比原始代码快,但使用查找表的方法仍然会快得多。

在我的慢速笔记本电脑上,你的原始代码〜28秒用于处理2.5亿个数字,并且用接受到的答案代码约23秒。使用查找表,只需要 7s

当您查看代码时,显而易见的原因是:

bool HasZero(int num)
{
    if (num < 100000) return lookup[num];

    int upperDigits = num / 100000;
    int lowerDigits = num - (upperDigits * 100000);

    return lookup[upperDigits] || lowerDigits < 10000 || lookup[lowerDigits];
}

代码具有一个除法,一个减法,一个乘法,两个比较和两个数组查找的最大。即使是优化,逐位数字也可能太多。并且预先计算查找表需要花费大量时间(<1ms)。

请注意,如果您不使用32位整数,代码将无法正常工作,因为那时您需要验证第三组数字(或将查找表的大小从10 ^ 5增加到10 ^ 6;我想它仍然会更快。)

答案 2 :(得分:0)

一个小主意。除常数的除法可以用乘法和移位序列代替。如果您使用的编译器或虚拟机有线索,那么它将自己执行此操作。如果它是愚蠢的,你可以通过手动插入乘法和移位序列来获得一些主要的加速。例如,对于Java HotSpot客户端虚拟机,我发现下面的技术(非负n的正确性)是执行除法的明显方式(注释掉)的两倍以上,并且速度快了五倍作为使用modulo的原始循环。

static boolean has0(int n) {
    do {
        //int divided = n / 10;
        int divided = (int)((n * 0xCCCCCCCDL) >>> 35);
        if (divided * 10 == n) return true;
        n = divided;
    } while (n != 0);
    return false;
}

但对于Java HotSpot Server虚拟机来说,这种显着的方法已经很快了,而且这个技巧已经很快了,这个技巧也无济于事,甚至让它变慢。不幸的是,通过这种非常低级别的优化,你必须准备好为不同的语言和语言实现重新调整它。

在尝试测量此类内容之前,请先阅读weird and wonderful complexities of microbenchmarking in Java

答案 3 :(得分:-2)

如果没有== 0,您的函数将返回false。除此之外,我无法看到你如何做得更好。