Domanda

Vorrei sapere come posso trovare la lunghezza di un numero intero in C.

Per esempio:

  • 1 => 1
  • 25 => 2
  • 12512 => 5
  • 0 => 1

e così via.

Come posso fare questo in C?

È stato utile?

Soluzione

C:

Perché non basta prendere il logaritmo in base 10 del valore assoluto del numero, rotondo verso il basso, e aggiungere uno? Questo funziona per numeri positivi e negativi che non sono 0, e evita di dover utilizzare le funzioni di conversione stringa.

I log10, abs, e le funzioni floor sono forniti da math.h. Ad esempio:

int nDigits = floor(log10(abs(the_integer))) + 1;

Si dovrebbe avvolgere questo in una clausola di garantire che the_integer != 0, dal momento che i rendimenti log10(0) -HUGE_VAL secondo le man 3 log.

Inoltre, è possibile aggiungere uno al risultato finale se l'ingresso è negativo, se siete interessati nella lunghezza del numero compreso il suo segno negativo.

Java:

int nDigits = Math.floor(Math.log10(Math.abs(the_integer))) + 1;

NB. La natura virgola mobile dei calcoli coinvolti in questo metodo può causare che sia più lento di un approccio più diretto. Vedere i commenti per la risposta di Kangkan per una discussione di efficienza.

Altri suggerimenti

Se siete interessati a un veloce e molto semplice soluzione, quanto segue potrebbe essere più veloce (questo dipende dalla distribuzione di probabilità dei numeri in questione):

int lenHelper(unsigned x) {
    if (x >= 1000000000) return 10;
    if (x >= 100000000)  return 9;
    if (x >= 10000000)   return 8;
    if (x >= 1000000)    return 7;
    if (x >= 100000)     return 6;
    if (x >= 10000)      return 5;
    if (x >= 1000)       return 4;
    if (x >= 100)        return 3;
    if (x >= 10)         return 2;
    return 1;
}

int printLen(int x) {
    return x < 0 ? lenHelper(-x) + 1 : lenHelper(x);
}

Anche se potrebbe non vincere premi per la soluzione più ingegnosa, è banale per capire e anche banale per l'esecuzione -. Così è veloce

In una Q6600 utilizzando MSC I benchmark con il seguente ciclo:

int res = 0;
for(int i = -2000000000; i < 2000000000; i += 200) res += printLen(i);

Questa soluzione prende 0.062s, il secondo miglior soluzione da Pete Kirkham utilizzando un approccio smart-logaritmo prende 0.115s - quasi il doppio del tempo. Tuttavia, per i numeri di circa 10000 e al di sotto, la smart-log è più veloce.

A scapito di una certa chiarezza, è possibile in modo più affidabile battere smart-log (almeno, su un Q6600):

int lenHelper(unsigned x) { 
    // this is either a fun exercise in optimization 
    // or it's extremely premature optimization.
    if(x >= 100000) {
        if(x >= 10000000) {
            if(x >= 1000000000) return 10;
            if(x >= 100000000) return 9;
            return 8;
        }
        if(x >= 1000000) return 7;
        return 6;
    } else {
        if(x >= 1000) {
            if(x >= 10000) return 5;
            return 4;
        } else {
            if(x >= 100) return 3;
            if(x >= 10) return 2;
            return 1;
        }
    }
}

Questa soluzione è ancora 0.062s sui grandi numeri, e si degrada a circa 0.09s per i numeri più piccoli - più veloce in entrambi i casi che l'approccio smart-log. (Gcc rende il codice più veloce; 0,052 per questa soluzione e 0.09s per l'approccio smart-log).

int get_int_len (int value){
  int l=1;
  while(value>9){ l++; value/=10; }
  return l;
}

e la seconda uno lavorerà per i numeri negativi anche:

int get_int_len_with_negative_too (int value){
  int l=!value;
  while(value){ l++; value/=10; }
  return l;
}

È possibile scrivere una funzione come questa:

unsigned numDigits(const unsigned n) {
    if (n < 10) return 1;
    return 1 + numDigits(n / 10);
}

lunghezza n:

length =  ( i==0 ) ? 1 : (int)log10(n)+1;

Il numero di cifre di un numero intero x è uguale a 1 + log10(x). Così si può fare questo:

#include <math.h>
#include <stdio.h>

int main()
{
    int x;
    scanf("%d", &x);
    printf("x has %d digits\n", 1 + (int)log10(x));
}

In alternativa, è possibile eseguire un ciclo per contare le cifre da soli: fare integer divisione per 10 fino a quando il numero è 0:

int numDigits = 0;
do
{
    ++numDigits;
    x = x / 10;
} while ( x );

Devi essere un po 'attenti a tornare 1 se l'intero è 0 nella prima soluzione e si potrebbe anche voler interi negativi treat (lavoro con -x se x < 0).

Il modo più efficace potrebbe essere quella di utilizzare un approccio basato logaritmo veloce, simili a quelle utilizzate per determinare la prima serie bit in un numero intero.

size_t printed_length ( int32_t x )
{
    size_t count = x < 0 ? 2 : 1;

    if ( x < 0 ) x = -x;

    if ( x >= 100000000 ) {
        count += 8;
        x /= 100000000;
    }

    if ( x >= 10000 ) {
        count += 4;
        x /= 10000;
    }

    if ( x >= 100 ) {
        count += 2;
        x /= 100;
    }

    if ( x >= 10 )
        ++count;

    return count;
}

Questa (forse prematuro) l'ottimizzazione prende 0.65s per 20 milioni di chiamate sul mio netbook; divisione iterativa come zed_0xff ha prende 1.6s, divisione ricorsiva come Kangkan prende 1.8s, e tramite le funzioni virgola mobile (codice Jordan Lewis') richiede 6.6s enorme. Utilizzando snprintf prende 11.5s, ma vi darà la dimensione che richiede snprintf per qualsiasi formato, non solo numeri interi. Jordan riferisce che l'ordinamento dei tempi non sono mantenuti sul suo processore, che non a virgola mobile più veloce del mio.

Il metodo più semplice è probabilmente quello di chiedere snprintf per la lunghezza stampata:

#include <stdio.h>

size_t printed_length ( int x )
{
    return snprintf ( NULL, 0, "%d", x );
}

int main ()
{
    int x[] = { 1, 25, 12512, 0, -15 };

    for ( int i = 0; i < sizeof ( x ) / sizeof ( x[0] ); ++i )
        printf ( "%d -> %d\n", x[i], printed_length ( x[i] ) );

    return 0;
}

Sì, utilizzando sprintf.

int num;
scanf("%d",&num);
char testing[100];
sprintf(testing,"%d",num);
int length = strlen(testing);

In alternativa, si può fare questo matematicamente utilizzando la funzione di log10.

int num;
scanf("%d",&num);
int length;
if (num == 0) {
  length = 1;
} else {    
  length = log10(fabs(num)) + 1;
  if (num < 0) length++;
}

Un'implementazione snprintf corretta:

int count = snprintf(NULL, 0, "%i", x);
int digits=1;

while (x>=10){
    x/=10;
    digits++;
}
return digits;
sprintf(s, "%d", n);
length_of_int = strlen(s);

È possibile utilizzare questo -

(data_type) log10 (nome_variabile) +1

es:

  

len = (int) log10 (numero) +1;

Molto semplice

int main() {
    int num = 123;
    char buf[50];

    // convert 123 to string [buf]
    itoa(num, buf, 10);

    // print our string
    printf("%s\n", strlen (buf));

    return 0;
}

continuare a dividere per dieci fino ad arrivare a zero, poi basta uscita il numero di divisioni.

int intLen(int x)
{
  if(!x) return 1;
  int i;
  for(i=0; x!=0; ++i)
  {
    x /= 10;
  }
  return i;
}

A mio parere la soluzione più breve e più semplice potrebbe essere:

int length , n;

printf("Enter a number: ");

scanf("%d", &n);

length = 0;

while (n > 0) {
   n = n / 10;
   length++;
}

printf("Length of the number: %d", length);

Il mio modo:

Divide fintanto che il numero non è più divisibili è di 10:

u8 NumberOfDigits(u32 number)
{
    u8 i = 1;
    while (number /= 10) i++;

    return i;
}

Non so quanto velocemente è a confronto con altre proposizioni ..

int intlen(int integer){
    int a;
    for(a = 1; integer /= 10; a++);
    return a;
}

Un più dettagliato modo sarebbe quello di utilizzare questa funzione.

int length(int n)
{
    bool stop;
    int nDigits = 0;
    int dividend = 1;
    do
    {
        stop = false;
        if (n > dividend)
        {
            nDigits = nDigits + 1;
            dividend = dividend * 10;
        }
        else {
            stop = true;
        }


    }
    while (stop == false);
    return nDigits;
}

Questo vale per sia negativi che positivi intigers

    int get_len(int n)
    {
        if(n == 0)
        return 1;

        if(n < 0)    
        {
           n = n * (-1); // if negative
        }

        return  log10(n) + 1;
    }

stessa logica vale per ciclo

  int get_len(int n)
  {
       if(n == 0)
       return 1;

       int len = 0;
       if(n < 0)
       n = n * (-1);

       while(n > 1)
       {
          n /= 10;
          len++;
       }

       return len;
  }
int returnIntLength(int value){
    int counter = 0;
    if(value < 0)
    {
        counter++;
        value = -value;
    }
    else if(value == 0)
        return 1;

    while(value > 0){
        value /= 10;
        counter++;
    }

    return counter;
}

Credo che questo metodo è adatto per questo compito:

Valore e risponde:

  • -50 -> 3 // conterà - come un carattere così se non volete contare                meno quindi rimuovere contatore ++ dalla linea 5.

  • 566666 -> 6

  • 0 -> 1

  • 505 -> 3

Penso che ho avuto il modo più efficace per trovare la lunghezza di un numero intero è un modo molto semplice ed elegante qui è:

int PEMath::LengthOfNum(int Num)
{
int count = 1;  //count starts at one because its the minumum amount of digits posible
if (Num < 0)
{
    Num *= (-1);
}

for(int i = 10; i <= Num; i*=10)
{
     count++;
}      
return count;
                // this loop will loop until the number "i" is bigger then "Num"
                // if "i" is less then "Num" multiply "i" by 10 and increase count
                // when the loop ends the number of count is the length of "Num".
}

int main (void) {     unsigned int n, size = 0;

printf("get the int:");
scanf("%u",&n);

/*the magic*/
for(int i = 1; n >= i; i*=10){
    size++;
}

printf("the value is: %u \n", n);
printf("the size is: %u \n", size);

return 0;

}

Si prega di trovare la mia risposta è in una sola linea di codice:

#include <stdio.h> int main(void){ int c = 12388884; printf("length of integer is: %d",printf("%d",c)); return 0; }

che è semplice e intelligente! Upvote se ti piace questo!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top