Как найти количество цифр целого положительного числа

There’s always this method:

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

Slai's user avatar

Slai

21.9k5 gold badges44 silver badges52 bronze badges

answered Jul 11, 2011 at 15:57

Mike Dunlavey's user avatar

Mike DunlaveyMike Dunlavey

39.9k14 gold badges91 silver badges135 bronze badges

3

Well the correct answer would be to measure it – but you should be able to make a guess about the number of CPU steps involved in converting strings and going through them looking for an end marker

Then think how many FPU operations/s your processor can do and how easy it is to calculate a single log.

edit: wasting some more time on a monday morning 🙂

String s = new Integer(t).toString(); 
int len = s.length();

One of the problems with high level languages is guessing how much work the system is doing behind the scenes of an apparently simple statement. Mandatory Joel link

This statement involves allocating memory for a string, and possibly a couple of temporary copies of a string. It must parse the integer and copy the digits of it into a string, possibly having to reallocate and move the existing memory if the number is large. It might have to check a bunch of locale settings to decide if your country uses “,” or “.”, it might have to do a bunch of unicode conversions.
Then finding the length has to scan the entire string, again considering unicode and any local specific settings such as – are you in a right->left language?.

Alternatively:

digits = floor( log10( number ) ) + 1;

Just because this would be harder for you to do on paper doesn’t mean it’s hard for a computer! In fact a good rule in high performance computing seems to have been – if something is hard for a human (fluid dynamics, 3d rendering) it’s easy for a computer, and if it’s easy for a human (face recognition, detecting a voice in a noisy room) it’s hard for a computer!

You can generally assume that the builtin maths functions log/sin/cos etc – have been an important part of computer design for 50years. So even if they don’t map directly into a hardware function in the FPU you can bet that the alternative implementation is pretty efficient.

answered Jul 11, 2011 at 15:14

Martin Beckett's user avatar

Martin BeckettMartin Beckett

94.4k28 gold badges186 silver badges261 bronze badges

4

I don’t know, and the answer may well be different depending on how your individual language is implemented.

So, stress test it! Implement all three solutions. Run them on 1 through 1,000,000 (or some other huge set of numbers that’s representative of the numbers the solution will be running against) and time how long each of them takes.

Pit your solutions against one another and let them fight it out. Like intellectual gladiators. Three algorithms enter! One algorithm leaves!

answered Jul 11, 2011 at 15:13

BlairHippo's user avatar

0

Test conditions

  • Decimal numeral system
  • Positive integers
  • Up to 10 digits
  • Language: ActionScript 3

Results

digits: [1,10],

no. of runs: 1,000,000

random sample: 8777509,40442298,477894,329950,513,91751410,313,3159,131309,2

result: 7,8,6,6,3,8,3,4,6,1

CONVERSION TO STRING: 724ms

LOGARITMIC CALCULATION: 349ms

DIV 10 ITERATION: 229ms

MANUAL CONDITIONING: 136ms

Note: Author refrains from making any conclusions for numbers with more than 10 digits.


Script

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

answered Jul 12, 2011 at 13:11

daniel.sedlacek's user avatar

daniel.sedlacekdaniel.sedlacek

8,0099 gold badges45 silver badges77 bronze badges

2

This algorithm might be good also, assuming that:

  • Number is integer and binary encoded (<< operation is cheap)
  • We don’t known number boundaries

    var num = 123456789L;
    var len = 0;
    var tmp = 1L;
    while(tmp < num)
    {
        len++;
        tmp = (tmp << 3) + (tmp << 1);
    }
    

This algorithm, should have speed comparable to for-loop (2) provided, but a bit faster due to (2 bit-shifts, add and subtract, instead of division).

As for Log10 algorithm, it will give you only approximate answer (that is close to real, but still), since analytic formula for computing Log function have infinite loop and can’t be calculated precisely Wiki.

eyllanesc's user avatar

eyllanesc

233k19 gold badges161 silver badges234 bronze badges

answered Jul 11, 2011 at 18:05

Valera Kolupaev's user avatar

6

Use the simplest solution in whatever programming language you’re using. I can’t think of a case where counting digits in an integer would be the bottleneck in any (useful) program.

C, C++:

char buffer[32];
int length = sprintf(buffer, "%ld", (long)123456789);

Haskell:

len = (length . show) 123456789

JavaScript:

length = String(123456789).length;

PHP:

$length = strlen(123456789);

Visual Basic (untested):

length = Len(str(123456789)) - 1

answered Jul 11, 2011 at 19:48

Joey Adams's user avatar

Joey AdamsJoey Adams

41.6k18 gold badges85 silver badges115 bronze badges

2

  • conversion to string: This will have to iterate through each digit, find the character that maps to the current digit, add a character to a collection of characters. Then get the length of the resulting String object. Will run in O(n) for n=#digits.

  • for-loop: will perform 2 mathematical operation: dividing the number by 10 and incrementing a counter. Will run in O(n) for n=#digits.

  • logarithmic: Will call log10 and floor, and add 1. Looks like O(1) but I’m not really sure how fast the log10 or floor functions are. My knowledge of this sort of things has atrophied with lack of use so there could be hidden complexity in these functions.

So I guess it comes down to: is looking up digit mappings faster than multiple mathematical operations or whatever is happening in log10? The answer will probably vary. There could be platforms where the character mapping is faster, and others where doing the calculations is faster. Also to keep in mind is that the first method will creats a new String object that only exists for the purpose of getting the length. This will probably use more memory than the other two methods, but it may or may not matter.

answered Jul 11, 2011 at 15:17

FrustratedWithFormsDesigner's user avatar

1

You can obviously eliminate the method 1 from the competition, because the atoi/toString algorithm it uses would be similar to method 2.

Method 3’s speed depends on whether the code is being compiled for a system whose instruction set includes log base 10.

answered Jul 11, 2011 at 15:39

user240515's user avatar

user240515user240515

3,0061 gold badge27 silver badges34 bronze badges

For very large integers, the log method is much faster. For instance, with a 2491327 digit number (the 11920928th Fibonacci number, if you care), Python takes several minutes to execute the divide-by-10 algorithm, and milliseconds to execute 1+floor(log(n,10)).

answered Aug 31, 2012 at 19:51

Brian Minton's user avatar

Brian MintonBrian Minton

3,2863 gold badges35 silver badges41 bronze badges

import math
def numdigits(n):
    return ( int(math.floor(math.log10(n))) + 1 )

Vivek Gani's user avatar

answered Mar 28, 2013 at 20:10

Alex's user avatar

AlexAlex

372 bronze badges

2

Regarding the three methods you propose for “determining the number of digits necessary to represent a given number in a given base”, I don’t like any of them, actually; I prefer the method I give below instead.

Re your method #1 (strings): Anything involving converting back-and-forth between strings and numbers is usually very slow.

Re your method #2 (temp/=10): This is fatally flawed because it assumes that x/10 always means “x divided by 10”. But in many programming languages (eg: C, C++), if “x” is an integer type, then “x/10” means “integer division”, which isn’t the same thing as floating-point division, and it introduces round-off errors at every iteration, and they accumulate in a recursive formula such as your solution #2 uses.

Re your method #3 (logs): it’s buggy for large numbers (at least in C, and probably other languages as well), because floating-point data types tend not to be as precise as 64-bit integers.

Hence I dislike all 3 of those methods: #1 works but is slow, #2 is broken, and #3 is buggy for large numbers. Instead, I prefer this, which works for numbers from 0 up to about 18.44 quintillion:

unsigned NumberOfDigits (uint64_t Number, unsigned Base)
{
   unsigned Digits = 1;
   uint64_t Power  = 1;
   while ( Number / Power >=  Base )
   {
      ++Digits;
      Power *= Base;
   }
   return Digits;
}

answered Apr 24, 2018 at 2:38

Robbie Hatley's user avatar

Keep it simple:

long long int a = 223452355415634664;

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

printf("%d", x);

answered Jul 11, 2011 at 17:52

Gary Willoughby's user avatar

Gary WilloughbyGary Willoughby

50.4k41 gold badges133 silver badges199 bronze badges

You can use a recursive solution instead of a loop, but somehow similar:

@tailrec
def digits (i: Long, carry: Int=1) : Int =  if (i < 10) carry else digits (i/10, carry+1)

digits (8345012978643L)

With longs, the picture might change – measure small and long numbers independently against different algorithms, and pick the appropriate one, depending on your typical input. 🙂

Of course nothing beats a switch:

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
}

except a plain-o-array:

   int [] size = {1,1,1,1,1,1,1,1,1,2,2,2,2,2,... };
   int x = 234561798;
   return size [x];

Some people will tell you to optimize the code-size, but yaknow, premature optimization …

answered Jul 12, 2011 at 13:41

user unknown's user avatar

user unknownuser unknown

35.3k11 gold badges75 silver badges121 bronze badges

log(x,n)-mod(log(x,n),1)+1

Where x is a the base and n is the number.

answered Apr 8, 2017 at 19:00

Tom's user avatar

1

Here is the measurement in Swift 4.

Algorithms code:

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
    }

}

Measurement code:

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))")

Output

timeInterval0: 1.92149806022644

timeInterval1: 0.557608008384705

timeInterval2: 2.83262193202972

On this measurement basis String conversion is the best option for the Swift language.

answered Jan 31, 2018 at 11:05

Ivan Smetanin's user avatar

Ivan SmetaninIvan Smetanin

1,9792 gold badges21 silver badges28 bronze badges

I was curious after seeing @daniel.sedlacek results so I did some testing using Swift for numbers having more than 10 digits. I ran the following script in the playground.

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)

Results of 80 elements

0.105069875717163 for floor(log10(x))
0.867973804473877 for div 10 iterations

answered Jun 3, 2016 at 12:16

twodayslate's user avatar

twodayslatetwodayslate

2,7933 gold badges27 silver badges43 bronze badges

Adding one more approach to many of the already mentioned approaches.
The idea is to use binarySearch on an array containing the range of integers based on the digits of the int data type.
The signature of Java Arrays class binarySearch is :
binarySearch(dataType[] array, dataType key) which returns the index of the search key, if it is contained in the array; otherwise, (-(insertion point) – 1).
The insertion point is defined as the point at which the key would be inserted into the array.
Below is the implementation:

    static int [] digits = {9,99,999,9999,99999,999999,9999999,99999999,999999999,Integer.MAX_VALUE};
    static int digitsCounter(int N)
    {
        int digitCount = Arrays.binarySearch(digits , N<0 ? -N:N);
        return 1 + (digitCount < 0 ? ~digitCount : digitCount);
    }

Please note that the above approach only works for : Integer.MIN_VALUE <= N <= Integer.MAX_VALUE, but can be easily extended for Long data type by adding more values to the digits array.


For example,
I) for N = 555, digitCount = Arrays.binarySearch(digits , 555) returns -3 (-(2)-1) as it’s not present in the array but is supposed to be inserted at point 2 between 9 & 99 like [9, 55, 99].
As the index we got is negative we need to take the bitwise compliment of the result.
At last, we need to add 1 to the result to get the actual number of digits in the number N.

answered Jun 25, 2021 at 6:41

GURU Shreyansh's user avatar

GURU ShreyanshGURU Shreyansh

8711 gold badge6 silver badges18 bronze badges

In Swift 5.x, you get the number of digit in integer as below :

  1. Convert to string and then count number of character in string
    let nums = [1, 7892, 78, 92, 90]
    for i in nums {
      let ch = String(describing: i)
      print(ch.count)
    }

  1. Calculating the number of digits in integer using loop
    var digitCount = 0
   for i in nums {
     var tmp = i
     while tmp >= 1 {
       tmp /= 10
       digitCount += 1
     }
     print(digitCount)
   }

cigien's user avatar

cigien

57.1k11 gold badges70 silver badges108 bronze badges

answered Feb 12, 2022 at 19:42

yo2bh's user avatar

yo2bhyo2bh

1,3261 gold badge14 silver badges26 bronze badges

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

F# Version, without casting to a string.

answered Dec 15, 2019 at 20:56

NomenNescio's user avatar

NomenNescioNomenNescio

2,8898 gold badges43 silver badges82 bronze badges

Студворк — интернет-сервис помощи студентам

Описать процедуру DigitCount(K,C), находящую C — количество цифр целого положительного числа K (K — входной, C — выходной параметры целого типа). С помощью этой процедуры найти и напечатать количество цифр для каждого из пяти данных чисел.

Формат входных данных
На вход программе подается 5 натуральных чисел, каждое из которых записано в отдельной строке. Числа не превосходят 2×109 и не содержат ведущих нулей.
Формат выходных данных
Требуется вывести 5 чисел — для каждого числа количество его цифр.
Примеры
входные данные выходные данные
12
234
456
4
12333
========
2
3
3
1
5

Формулировка задачи:

Описать функцию DigitCount(K) целого типа, находящую количество цифр целого положительного числа K. Используя эту функцию, найти количество цифр для каждого из пяти данных целых положительных чисел.

Код к задаче: «Найти количество цифр целого положительного числа K»

textual

int digit_count(int k) {
    int i;
    for (i = 1; k /= 10; i++)
        ;
    return i;
}

Полезно ли:

13   голосов , оценка 3.923 из 5

Описание задачи

Программа принимает число и выводит количество цифр в нем.

Решение задачи

  1. Берем значение целого числа и записываем его в переменную.
  2. Используем цикл while и при помощи оператора целочисленного деления «уничтожаем» каждую цифру числа начиная с последней, а при каждой итерации цикла специально созданную переменную (так называемый счетчик цикла) увеличиваем на единицу. После того как введенное в начале число станет равным 0, цикл прекратит свою работу.
  3. Выводим значение этого счетчика на экран.
  4. Конец.

Исходный код

Ниже дан исходный код для подсчета количества цифр в данном числе. Результаты работы программы также даны ниже.

n = int(input("Введите число:"))
count = 0
while(n > 0):
    count = count + 1
    n = n // 10
print("Количество цифр равно:", count)

Объяснение работы программы

  1. Записываем введенное пользователем число в переменную n.
  2. Задаем переменную count и инициируем ее значением 0.
  3. Используем цикл while и при помощи оператора целочисленного деления «уничтожаем» каждую цифру числа начиная с конца.
  4. При каждой итерации цикла переменная count увеличивается на 1.
  5. Как только цифры в числе заканчиваются и число n становится равным 0, цикл прекращает свою работу.
  6. Выводим переменную count на экран.

Результаты работы программы

Пример 1:
Введите число:123
Количество цифр равно: 3
 
Пример 2:
Введите число:1892
Количество цифр равно: 4

Примечание переводчика

Надо заметить, что опять эту задачу можно решить намного короче, если использовать методы строк.

print("Количество цифр равно:", len(input("Введите число:")))

Здесь введенное число принимается как строка и мы просто выводим ее длину.

A PHP Error was encountered

Severity: Warning

Message: fopen(/var/www/u944000/data/mod-tmp/ci_session19f832237632516f83529bbc5aba10eb2e54393d): failed to open stream: Disk quota exceeded

Filename: drivers/Session_files_driver.php

Line Number: 174

Backtrace:

File: /var/www/u944000/data/www/mycod.net/application/core/MY_Controller.php
Line: 9
Function: __construct

File: /var/www/u944000/data/www/mycod.net/application/controllers/Abramyancatalog.php
Line: 8
Function: __construct

File: /var/www/u944000/data/www/mycod.net/index.php
Line: 315
Function: require_once

A PHP Error was encountered

Severity: Warning

Message: session_start(): Failed to read session data: user (path: /var/www/u944000/data/mod-tmp)

Filename: Session/Session.php

Line Number: 143

Backtrace:

File: /var/www/u944000/data/www/mycod.net/application/core/MY_Controller.php
Line: 9
Function: __construct

File: /var/www/u944000/data/www/mycod.net/application/controllers/Abramyancatalog.php
Line: 8
Function: __construct

File: /var/www/u944000/data/www/mycod.net/index.php
Line: 315
Function: require_once

Вопрос по DCOMPermissions.psm1


19th April, 17:09


172


0

Некорректный скрипт для закрытия блока


14th April, 18:33


157


0

Doesn’t show model window


14th March, 22:20


155


0

прокидывать exception в блоках try-catch JAVA


11th March, 21:11


168


0

Пишу BAS-скрипты на запросах для несложных сайтов и Android-приложений.


9th February, 17:04


405


0

Помогите пожалуйста решить задачи


24th November, 23:53


985


0

Не понимаю почему не открывается детальное описание продукта


11th November, 11:51


396


0

Пишу скрипты для BAS только на запросах


8th November, 10:38


459


0

Как поднять свой VPN на Android?


4th November, 17:09


474


1

Нужно решить задачу по программированию на массивы


27th October, 18:01


617


0

Метода Крамера С++


23rd October, 11:55


499


0

помогите решить задачу на C++


22nd October, 17:31


516


0

Помогите решить задачу на python с codeforces


22nd October, 11:11


637


0

Generate Additional Engagement Image Masking Service


5th July, 07:34


730


0

Join Us Today Ghost Mannequin Effect Service


5th July, 07:10


904


0

Python с нуля


18th June, 13:58


805


0

Its Urban Malaysia Phone Number List Exceeds 


21st April, 08:09


930


1

橱柜并烤 手机号码 了一个纸杯蛋糕之后


6th April, 13:05


567


0

Все вопросы

По разделам

 

Описать функцию DigitCount(K) целого типа, находящую количество
цифр целого положительного числа K. Используя эту функцию, найти количество цифр для каждого из пяти данных целых положительных чисел.

Добавить комментарий