Algorithm 查找整数的位数

Algorithm 查找整数的位数,algorithm,digits,counting,Algorithm,Digits,Counting,求正整数位数的最佳方法是什么 我发现了这3种基本方法: 转换为字符串 String s = new Integer(t).toString(); int len = s.length(); for循环 for(long long int temp = number; temp >= 1;) { temp/=10; decimalPlaces++; } 对数计算 digits = floor( log10( number ) ) + 1; 其中可以计算大多

求正整数位数的最佳方法是什么

我发现了这3种基本方法:

  • 转换为字符串

    String s = new Integer(t).toString(); 
    int len = s.length();
    
  • for循环

    for(long long int temp = number; temp >= 1;)
    {
        temp/=10;
        decimalPlaces++;
    } 
    
  • 对数计算

    digits = floor( log10( number ) ) + 1;
    
其中可以计算大多数语言中的log10(x)=ln(x)/ln(10)


首先我认为string方法是最肮脏的方法,但是我越想它,我就越觉得它是最快的方法。或者是吗?

我不知道,答案可能会有所不同,这取决于您个人语言的实现方式

所以,压力测试吧!实施所有三种解决方案。在1到1000000(或代表解决方案将要运行的数字的一些其他大型数字集)上运行它们,并计算它们所需的时间


让你的解决方案互相对抗,让他们来解决。就像智力角斗士。三个算法进入!一个算法离开

正确的答案应该是测量它-但是您应该能够猜测转换字符串和查找结束标记所涉及的CPU步骤数

然后想想您的处理器可以执行多少FPU操作,以及计算单个日志有多容易

编辑:在周一早上浪费更多时间:-)

高级语言的一个问题是猜测系统在一个明显简单的语句背后做了多少工作。强制性的

此语句涉及为字符串分配内存,可能还包括字符串的两个临时副本。它必须解析整数并将其数字复制到字符串中,如果数字较大,则可能需要重新分配和移动现有内存。它可能需要检查一组区域设置,以确定您的国家是否使用“,”或“.”,它可能需要进行一组unicode转换。
然后查找长度必须扫描整个字符串,再次考虑unicode和任何特定于本地的设置,例如-您使用的是右->左语言吗

或者:

digits = floor( log10( number ) ) + 1;
仅仅因为这对你来说在纸上做起来比较困难并不意味着对电脑来说就很难!事实上,高性能计算中的一个好规则似乎是——如果某些东西对人来说很难(流体动力学、3d渲染),那么对计算机来说很容易;如果对人来说很容易(人脸识别、在嘈杂的房间里检测声音),那么对计算机来说很难

一般来说,你可以假设内置的数学函数log/sin/cos等——50年来一直是计算机设计的重要组成部分。因此,即使它们没有直接映射到FPU中的硬件功能,您也可以打赌替代实现相当有效。

  • 转换为字符串:必须遍历每个数字,找到映射到当前数字的字符,将字符添加到字符集合中。然后获取结果字符串对象的长度。将在O(n)中运行n=#位

  • for循环:将执行2个数学运算:将数字除以10并递增一个计数器。将在O(n)中运行n=#位

  • 对数:将调用log10和floor,并添加1。看起来像O(1),但我不确定log10或楼层功能的速度有多快。我对这类东西的知识由于缺乏使用而萎缩,因此这些函数中可能隐藏着复杂性


所以我想它归结为:查找数字映射是否比多重数学运算或在
log10
中发生的任何事情都要快?答案可能会有所不同。有些平台的角色映射速度更快,而有些平台的计算速度更快。还要记住的是,第一个方法将创建一个新的String对象,该对象只存在于获取长度的目的。这可能会比其他两种方法使用更多的内存,但这可能有问题,也可能没有问题。

您显然可以将方法1从竞争中淘汰,因为它使用的atoi/toString算法与方法2类似


方法3的速度取决于是否为指令集包含log base 10的系统编译代码。

始终存在以下方法:

n = 1;
if ( i >= 100000000 ) { n += 8; i /= 100000000; }
if ( i >= 10000     ) { n += 4; i /= 10000; }
if ( i >= 100       ) { n += 2; i /= 100; }
if ( i >= 10        ) { n += 1; }
保持简单:

long long int a = 223452355415634664;

int x;
for (x = 1; a >= 10; x++)
{
   a = a / 10;
}

printf("%d", x);

假设:


  • 数字是整数和二进制编码的(在您使用的任何编程语言中使用最简单的解决方案。我想不出在任何情况下,整数中的数字计数会成为任何(有用的)程序的瓶颈

    C、 C++: 哈斯克尔: JavaScript: PHP: Visual Basic(未经测试):
    测试条件

    • 十进制数字系统
    • 正整数
    • 最多10位
    • 语言:动作脚本3
    结果

    数字:[1,10]

    跑步次数:1000000

    随机样本:87775094044229847789432995013917514103133159131309,2

    结果:7,8,6,6,3,8,3,4,6,1

    转换为字符串:724ms

    对数计算:349ms

    DIV 10迭代:229ms

    手动调节:136ms

    注:对于超过10位数的数字,作者不作任何结论


    脚本

    package {
        import flash.display.MovieClip;
        import flash.utils.getTimer;
        /**
         * @author Daniel
         */
        public class Digits extends MovieClip {
            private const NUMBERS : uint = 1000000;
            private const DIGITS : uint = 10;
    
            private var numbers : Array;
            private var digits : Array;
    
            public function Digits() {
                // ************* NUMBERS *************
                numbers = [];
                for (var i : int = 0; i < NUMBERS; i++) {
                    var number : Number = Math.floor(Math.pow(10, Math.random()*DIGITS));
                    numbers.push(number);
                }   
                trace('Max digits: ' + DIGITS + ', count of numbers: ' + NUMBERS);
                trace('sample: ' + numbers.slice(0, 10));
    
                // ************* CONVERSION TO STRING *************
                digits = [];
                var time : Number = getTimer();
    
                for (var i : int = 0; i < numbers.length; i++) {
                    digits.push(String(numbers[i]).length);
                }
    
                trace('\nCONVERSION TO STRING - time: ' + (getTimer() - time));
                trace('sample: ' + digits.slice(0, 10));
    
                // ************* LOGARITMIC CALCULATION *************
                digits = [];
                time = getTimer();
    
                for (var i : int = 0; i < numbers.length; i++) {
                    digits.push(Math.floor( Math.log( numbers[i] ) / Math.log(10) ) + 1);
                }
    
                trace('\nLOGARITMIC CALCULATION - time: ' + (getTimer() - time));
                trace('sample: ' + digits.slice(0, 10));
    
                // ************* DIV 10 ITERATION *************
                digits = [];
                time = getTimer();
    
                var digit : uint = 0;
                for (var i : int = 0; i < numbers.length; i++) {
                    digit = 0;
                    for(var temp : Number = numbers[i]; temp >= 1;)
                    {
                        temp/=10;
                        digit++;
                    } 
                    digits.push(digit);
                }
    
                trace('\nDIV 10 ITERATION - time: ' + (getTimer() - time));
                trace('sample: ' + digits.slice(0, 10));
    
                // ************* MANUAL CONDITIONING *************
                digits = [];
                time = getTimer();
    
                var digit : uint;
                for (var i : int = 0; i < numbers.length; i++) {
                    var number : Number = numbers[i];
                    if (number < 10) digit = 1;
                    else if (number < 100) digit = 2;  
                    else if (number < 1000) digit = 3;  
                    else if (number < 10000) digit = 4;  
                    else if (number < 100000) digit = 5;  
                    else if (number < 1000000) digit = 6;  
                    else if (number < 10000000) digit = 7;  
                    else if (number < 100000000) digit = 8;  
                    else if (number < 1000000000) digit = 9;  
                    else if (number < 10000000000) digit = 10;  
                    digits.push(digit);
                }
    
                trace('\nMANUAL CONDITIONING: ' + (getTimer() - time));
                trace('sample: ' + digits.slice(0, 10));
            }
        }
    }
    
    包{
    导入flash.display.MovieClip;
    导入flash.utils.getTimer;
    /**
    *@作者丹尼尔
    */
    公共类数字扩展MovieClip{
    私人施工编号:uint=1000000;
    专用常量位数:uint=10;
    私有变量数:数组;
    私有变量位:数组;
    公共函数数字(){
    //*************号码*************
    数字=[];
    对于(变量i:int=0;ivar num = 123456789L;
    var len = 0;
    var tmp = 1L;
    while(tmp < num)
    {
        len++;
        tmp = (tmp << 3) + (tmp << 1);
    }
    
    char buffer[32];
    int length = sprintf(buffer, "%ld", (long)123456789);
    
    len = (length . show) 123456789
    
    length = String(123456789).length;
    
    $length = strlen(123456789);
    
    length = Len(str(123456789)) - 1
    
    package {
        import flash.display.MovieClip;
        import flash.utils.getTimer;
        /**
         * @author Daniel
         */
        public class Digits extends MovieClip {
            private const NUMBERS : uint = 1000000;
            private const DIGITS : uint = 10;
    
            private var numbers : Array;
            private var digits : Array;
    
            public function Digits() {
                // ************* NUMBERS *************
                numbers = [];
                for (var i : int = 0; i < NUMBERS; i++) {
                    var number : Number = Math.floor(Math.pow(10, Math.random()*DIGITS));
                    numbers.push(number);
                }   
                trace('Max digits: ' + DIGITS + ', count of numbers: ' + NUMBERS);
                trace('sample: ' + numbers.slice(0, 10));
    
                // ************* CONVERSION TO STRING *************
                digits = [];
                var time : Number = getTimer();
    
                for (var i : int = 0; i < numbers.length; i++) {
                    digits.push(String(numbers[i]).length);
                }
    
                trace('\nCONVERSION TO STRING - time: ' + (getTimer() - time));
                trace('sample: ' + digits.slice(0, 10));
    
                // ************* LOGARITMIC CALCULATION *************
                digits = [];
                time = getTimer();
    
                for (var i : int = 0; i < numbers.length; i++) {
                    digits.push(Math.floor( Math.log( numbers[i] ) / Math.log(10) ) + 1);
                }
    
                trace('\nLOGARITMIC CALCULATION - time: ' + (getTimer() - time));
                trace('sample: ' + digits.slice(0, 10));
    
                // ************* DIV 10 ITERATION *************
                digits = [];
                time = getTimer();
    
                var digit : uint = 0;
                for (var i : int = 0; i < numbers.length; i++) {
                    digit = 0;
                    for(var temp : Number = numbers[i]; temp >= 1;)
                    {
                        temp/=10;
                        digit++;
                    } 
                    digits.push(digit);
                }
    
                trace('\nDIV 10 ITERATION - time: ' + (getTimer() - time));
                trace('sample: ' + digits.slice(0, 10));
    
                // ************* MANUAL CONDITIONING *************
                digits = [];
                time = getTimer();
    
                var digit : uint;
                for (var i : int = 0; i < numbers.length; i++) {
                    var number : Number = numbers[i];
                    if (number < 10) digit = 1;
                    else if (number < 100) digit = 2;  
                    else if (number < 1000) digit = 3;  
                    else if (number < 10000) digit = 4;  
                    else if (number < 100000) digit = 5;  
                    else if (number < 1000000) digit = 6;  
                    else if (number < 10000000) digit = 7;  
                    else if (number < 100000000) digit = 8;  
                    else if (number < 1000000000) digit = 9;  
                    else if (number < 10000000000) digit = 10;  
                    digits.push(digit);
                }
    
                trace('\nMANUAL CONDITIONING: ' + (getTimer() - time));
                trace('sample: ' + digits.slice(0, 10));
            }
        }
    }
    
    @tailrec
    def digits (i: Long, carry: Int=1) : Int =  if (i < 10) carry else digits (i/10, carry+1)
    
    digits (8345012978643L)
    
    switch (x) {
      case 0:  case 1:  case 2:  case 3:  case 4:  case 5:  case 6:  case 7:  case 8:  case 9: return 1;
      case 10: case 11: // ...
      case 99: return 2;
      case 100: // you get the point :) 
      default: return 10; // switch only over int
    }
    
       int [] size = {1,1,1,1,1,1,1,1,1,2,2,2,2,2,... };
       int x = 234561798;
       return size [x];
    
    import math
    def numdigits(n):
        return ( int(math.floor(math.log10(n))) + 1 )
    
    let base = [Double(100090000000), Double(100050000), Double(100050000), Double(100000200)]
    var rar = [Double]()
    for i in 1...10 {
        for d in base {
            let v = d*Double(arc4random_uniform(UInt32(1000000000)))
            rar.append(v*Double(arc4random_uniform(UInt32(1000000000))))
            rar.append(Double(1)*pow(1,Double(i)))
        }
    }
    
    print(rar)
    
    var timeInterval = NSDate().timeIntervalSince1970
    
    for d in rar {
        floor(log10(d))
    }
    
    var newTimeInterval = NSDate().timeIntervalSince1970
    
    print(newTimeInterval-timeInterval)
    
    
    timeInterval = NSDate().timeIntervalSince1970
    for d in rar {
        var c = d
        while c > 10 {
            c = c/10
        }
    }
    
    newTimeInterval = NSDate().timeIntervalSince1970
    
    print(newTimeInterval-timeInterval)
    
    extension Int {
        var numberOfDigits0: Int {
            var currentNumber = self
            var n = 1
            if (currentNumber >= 100000000) {
                n += 8
                currentNumber /= 100000000
            }
            if (currentNumber >= 10000) {
                n += 4
                currentNumber /= 10000
            }
            if (currentNumber >= 100) {
                n += 2
                currentNumber /= 100
            }
            if (currentNumber >= 10) {
                n += 1
            }
            return n
        }
    
        var numberOfDigits1: Int {
            return String(self).count
        }
    
        var numberOfDigits2: Int {
            var n = 1
            var currentNumber = self
            while currentNumber > 9 {
                n += 1
                currentNumber /= 10
            }
            return n
        }
    
    }
    
    var timeInterval0 = Date()
    for i in 0...10000 {
        i.numberOfDigits0
    }
    print("timeInterval0: \(Date().timeIntervalSince(timeInterval0))")
    
    var timeInterval1 = Date()
    for i in 0...10000 {
        i.numberOfDigits1
    }
    print("timeInterval1: \(Date().timeIntervalSince(timeInterval1))")
    
    var timeInterval2 = Date()
    for i in 0...10000 {
        i.numberOfDigits2
    }
    print("timeInterval2: \(Date().timeIntervalSince(timeInterval2))")
    
    unsigned NumberOfDigits (uint64_t Number, unsigned Base)
    {
       unsigned Digits = 1;
       uint64_t Power  = 1;
       while ( Number / Power >=  Base )
       {
          ++Digits;
          Power *= Base;
       }
       return Digits;
    }
    
    let numDigits num =
        let num = abs(num)
        let rec numDigitsInner num =
            match num with
            | num when num < 10 -> 1
            | _ -> 1 + numDigitsInner (num / 10)
        numDigitsInner num