سؤال

أود أن أعرف كيف يمكنني العثور على طول عدد صحيح في C.

على سبيل المثال:

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

وهلم جرا.

كيف يمكنني فعل هذا في ج؟

هل كانت مفيدة؟

المحلول

ج:

لماذا لا تأخذ فقط سجل الأساس 10 للقيمة المطلقة للرقم ، وقم حوله إلى أسفل ، وإضافة واحدة؟ هذا يعمل للأرقام الإيجابية والسلبية التي ليست 0 ، وتجنب الاضطرار إلى استخدام أي وظائف تحويل السلسلة.

ال log10, abs, ، و floor يتم توفير الوظائف بواسطة math.h. فمثلا:

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

يجب عليك لف هذا في جملة تأكد من ذلك the_integer != 0, ، حيث log10(0) عائدات -HUGE_VAL بالنسبة الى man 3 log.

بالإضافة إلى ذلك ، قد ترغب في إضافة واحدة إلى النتيجة النهائية إذا كان الإدخال سلبيًا ، إذا كنت مهتمًا بطول الرقم بما في ذلك العلامة السلبية.

جافا:

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

NB قد تتسبب الطبيعة الفاصلة في الحسابات التي تنطوي عليها هذه الطريقة إلى أن تكون أبطأ من النهج المباشر. شاهد تعليقات إجابة Kangkan لبعض النقاش حول الكفاءة.

نصائح أخرى

إذا كنت مهتمًا بـ سريع و بسيط جدا الحل ، قد يكون ما يلي أسرع (هذا يعتمد على توزيع احتمال الأرقام المعنية):

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

على الرغم من أنه قد لا يفوز بجوائز للحل الأكثر إبداعًا ، إلا أنه من التافهة أن نفهم وأيضًا تنفيذها - لذلك فهو سريع.

على Q6600 باستخدام MSC ، قامت بتقييم هذا مع الحلقة التالية:

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

يستغرق هذا الحل 0.062s ، وهو ثاني أسرع الحلول من قبل بيت كيركهام باستخدام نهج السفن الذكية يستغرق 0.115 ثانية-ما يقرب من ضعف طوله. ومع ذلك ، بالنسبة للأرقام حوالي 10000 وما يليها ، فإن السجل الذكي أسرع.

على حساب بعض الوضوح ، يمكنك التغلب على السطوح الذكية بشكل أكثر موثوقية (على الأقل ، على 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;
        }
    }
}

لا يزال هذا الحل 0.062s على أعداد كبيرة ، ويتحلل إلى حوالي 0.09s للأعداد الأصغر - أسرع في كلتا الحالتين من نهج السطوع الذكي. (تقوم GCC بتصنيع رمز أسرع ؛ 0.052 لهذا الحل و 0.09s لنهج السجل الذكي).

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

والثاني سيعمل للأرقام السلبية أيضًا:

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

يمكنك كتابة وظيفة مثل هذه:

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

طول N:

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

عدد أرقام عدد صحيح x مساوي ل 1 + log10(x). لذلك يمكنك القيام بذلك:

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

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

أو يمكنك تشغيل حلقة لحساب الأرقام بنفسك: قم بإجراء تقسيم عدد صحيح بمقدار 10 حتى يكون الرقم 0:

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

عليك أن تكون حذرا بعض الشيء للعودة 1 إذا كان عدد صحيح 0 في الحل الأول وقد ترغب أيضًا في علاج الأعداد الصحيحة السلبية (العمل مع -x إذا x < 0).

قد تكون الطريقة الأكثر كفاءة هي استخدام نهج سريع قائم على اللوغ ، على غرار تلك المستخدمة لتحديد أعلى بتات في عدد صحيح.

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

يستغرق هذا التحسين (ربما سابق لأوانه) 0.65 ثانية مقابل 20 مليون مكالمة على نتبووك ؛ يستغرق التقسيم التكراري مثل ZED_0XFF 1.6 ثانية ، ويأخذ التقسيم العودية مثل Kangkan 1.8 ثانية ، واستخدام وظائف النقطة العائمة (رمز الأردن لويس) يأخذ 6.6s هائلة. يستغرق استخدام SNPRINTF 11.5s ، ولكن سيعطيك الحجم الذي يتطلبه SNPRINTF لأي تنسيق ، وليس فقط الأعداد الصحيحة. يذكر الأردن أن ترتيب التوقيت لا يتم الحفاظ عليه على معالجه ، وهو ما يطفو بشكل أسرع من لي.

ربما يكون أسهل هو طلب Snprintf للطول المطبوع:

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

نعم ، باستخدام Sprintf.

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

بدلاً من ذلك ، يمكنك القيام بذلك رياضياً باستخدام log10 وظيفة.

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

صحيح snprintf تطبيق:

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

يمكنك استخدام هذا -

(data_type) log10 (variable_name) +1

السابق:

len = (int) log10 (number) +1 ؛

بسيط جدا

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

استمر في الانقسام على عشرة حتى تحصل على الصفر ، ثم فقط إخراج عدد الأقسام.

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

في رأيي ، سيكون حل أقصر وأسهل هو:

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

طريقى:

تقسيم طالما أن العدد لا يمكن تقسيمه بمقدار 10:

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

    return i;
}

لا أعرف مدى سرعة ذلك مقارنة بالمقترحات الأخرى ..

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

طريقة أكثر مطوّلة هي استخدام هذه الوظيفة.

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

هذا ينطبق على كل من الأطواق السلبية والإيجابية

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

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

        return  log10(n) + 1;
    }

نفس المنطق ينطبق على حلقة

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

أعتقد أن هذه الطريقة مناسبة تمامًا لهذه المهمة:

القيمة والإجابات:

  • -50 -> 3 // سيحسب -كحرف واحد أيضًا إذا كنت لا ترغب في حساب ناقص ثم إزالة Counter ++ من السطر الخامس.

  • 566666 -> 6

  • 0 -> 1

  • 505 -> 3

أعتقد أنني حصلت على الطريقة الأكثر فعالية لإيجاد طول عدد صحيح ، إنها طريقة بسيطة للغاية وأنيقة هنا هي:

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;

}

يرجى العثور على إجابتي إنه في رمز سطر واحد:

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

هذا بسيط وذكي! التصويت إذا كنت تحب هذا!

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top