इंट में अंकों की संख्या प्राप्त करने का तरीका?


385

क्या इस विधि की तुलना में इंट की लंबाई प्राप्त करने का कोई तरीका है?

int length = String.valueOf(1000).length();

7
कृपया एक इंट की लंबाई परिभाषित करें।
टॉम

24
मुझे लगता है कि वह अंकों को अंकों में गिनना चाहता है।
अल्बर्टो ज़ैकाग्नि

3
जो उत्तर लोग आपको दे रहे हैं वे सही हैं ... वे आपको एक स्ट्रिंग में परिवर्तित किए बिना int की लंबाई देते हैं ... लेकिन आप इसे स्ट्रिंग में बदलना क्यों नहीं चाहते हैं? क्या यह गति की बात है? यदि हां, तो मुझे विश्वास नहीं है कि ये विधियां और तेज़ होंगी ... आप कुछ परीक्षण करना चाहते हैं (या तय कर सकते हैं कि क्या यह भी मायने रखता है।)
बेस्का

3
@ptomli हेक्साडेसिमल अंक अभी भी एक अलग आधार प्रणाली में अंक हैं।
मार्क पिम

2
@Ptomli ज़रूर, लेकिन दोनों Integer.toString फ़ंक्शन में, और सामान्य बातचीत में, दशमलव डिफ़ॉल्ट है। जब बैंक मुझे बताता है, "इस बॉक्स में अपने चेक की मात्रा लिखें", मैं उनसे यह नहीं पूछता कि क्या मुझे इसे दशमलव, हेक्स, या ऑक्टल में लिखना चाहिए। हम दशमलव को तब तक मान लेते हैं जब तक कि उसे अन्यथा निर्दिष्ट या संदर्भ के लिए नहीं बुलाया जाता है।
जे

जवाबों:


349

आपका स्ट्रिंग-आधारित समाधान पूरी तरह से ठीक है, इसके बारे में "अन-नीट" कुछ भी नहीं है। आपको महसूस करना होगा कि गणितीय रूप से, संख्याओं की लंबाई नहीं है, न ही उनके पास अंक हैं। लंबाई और अंक दोनों एक विशिष्ट आधार में एक संख्या के भौतिक प्रतिनिधित्व के गुण हैं , अर्थात एक स्ट्रिंग।

एक लघुगणक-आधारित समाधान (कुछ) वही चीजें करता है जो स्ट्रिंग-आधारित एक आंतरिक रूप से करता है, और संभवत: ऐसा (तुच्छ रूप से) तेजी से करता है क्योंकि यह केवल लंबाई पैदा करता है और अंकों की उपेक्षा करता है। लेकिन मैं वास्तव में इसे इरादे में स्पष्ट नहीं मानूंगा - और यह सबसे महत्वपूर्ण कारक है।


54
एक समस्या को हल करने के लिए एक रास्ता चुनते समय कोड के इरादे पर विचार करने के लिए +1
pupeno

5
डाटापॉइंट: मेरी मशीन पर, लॉग विधि स्ट्रिंग लंबाई के तरीकों के रूप में दो बार के तहत बस चलाने के लिए लगता है। मैं उस महत्वहीन को फोन नहीं करूंगा यदि विधि को बहुत अधिक या कोड के महत्वपूर्ण समय खंड में कहा जाता है।
CPerkins

1
नीचे मेरा बेंचमार्क यूनिट टेस्ट देखें (जो त्रुटिपूर्ण हो सकता है मैं भी बेंचमार्क विशेषज्ञ नहीं हूं)। बड़ी संख्या में रन (100 000 000) से अधिक, मेरी मशीन पर गति 11s से 8s है जो शायद ही दो बार तेजी से होती है।
जीन

5
@CPerkins। समय से पहले अनुकूलन। आपको पता है कि स्पील।
माइकल बोर्गवर्ड्ट

11
कुछ (बहुत देर से) इसके अलावा: यह नकारात्मक मानों के लिए ठीक से काम नहीं कर सकता है, यह निर्भर करता है कि आप "-" अंक या नहीं होने की उम्मीद करते हैं। जोड़ने से Math.abs()यह ठीक हो जाएगा, हालांकि।
यिंगयांग

265

लघुगणक आपका मित्र है:

int n = 1000;
int length = (int)(Math.log10(n)+1);

NB: केवल n> 0 के लिए मान्य है।


2
और क्या यह मेरे वैरिएंट के उपयोग से तेज या बेहतर है?
fnst

+1: आपने मुझे एक सेकंड से हराया, और आपका जवाब सही था, जहां मेरा थोड़ा सा बंद था। ध्यान दें, हालांकि, यह संकलक एक लापता कलाकार के कारण शिकायत करेगा int
डिर्क

2
@ क्यों आप मानेंगे कि यह महंगा है? कोई यह मान सकता है कि गणित सह-प्रोसेसर इसे निष्पादित करेगा, इसलिए यह एक अतिरिक्त गति के करीब हो सकता है। यहां तक ​​कि अगर जावा अब सह-प्रोसेसर का उपयोग नहीं करता है, तो यह एक अच्छी धारणा है कि यह हो सकता है ... (हम सिर्फ आपके और अधिक अशिक्षित निहितार्थ को अनदेखा करेंगे कि जावा धीमा है क्योंकि आप शायद सबूतों में रुचि नहीं रखते हैं - या यदि आप शूटआउट.लिथ.बीडियन.ओआरजी पर जाते हैं और खुद पता लगाते हैं)
बिल के

8
कार्य करता है ... जब तक कि आप जो मूल्य जाँच रहे हैं = 0, जो आपको विषम परिणाम (-2147483647) देगा। Math.log10 एपीआई: "यदि तर्क सकारात्मक शून्य या नकारात्मक शून्य है, तो परिणाम नकारात्मक अनंत है।"
मुजिमु

2
+1 एक ऐसी विधि प्रस्तुत करना जिसमें ऑब्जेक्ट मेमोरी एलोकेशन शामिल नहीं है, जो GC संग्रह से बचने के लिए पुन: उपयोग को अधिकतम करने के लिए आवश्यक है।
माइकल वोजिक 1

158

सबसे तेज़ दृष्टिकोण: विभाजित और जीतना।

मान लें कि आपकी सीमा 0 से MAX_INT है, तो आपके पास 1 से 10 अंक हैं। आप प्रत्येक इनपुट के प्रति 4 तुलनाओं के साथ, विभाजन और जीत का उपयोग करके इस अंतराल को देख सकते हैं। सबसे पहले, आप एक तुलना के साथ [१.१०] को [१.५.५] और [६.१०] में विभाजित करते हैं, और फिर प्रत्येक लंबाई ५ अंतराल को आप एक तुलना में एक लंबाई ३ और एक लंबाई २ अंतराल में विभाजित करते हैं। लंबाई 2 अंतराल को एक और तुलना (कुल 3 तुलना) की आवश्यकता होती है, लंबाई 3 अंतराल को लंबाई 1 अंतराल (समाधान) और एक लंबाई 2 अंतराल में विभाजित किया जा सकता है। तो, आपको 3 या 4 तुलनाओं की आवश्यकता है।

कोई विभाजन नहीं, कोई फ़्लोटिंग पॉइंट ऑपरेशन नहीं, कोई महंगा लॉगरिथम नहीं, केवल पूर्णांक तुलना।

कोड (लंबे लेकिन तेज):

if (n < 100000){
        // 5 or less
        if (n < 100){
            // 1 or 2
            if (n < 10)
                return 1;
            else
                return 2;
        }else{
            // 3 or 4 or 5
            if (n < 1000)
                return 3;
            else{
                // 4 or 5
                if (n < 10000)
                    return 4;
                else
                    return 5;
            }
        }
    } else {
        // 6 or more
        if (n < 10000000) {
            // 6 or 7
            if (n < 1000000)
                return 6;
            else
                return 7;
        } else {
            // 8 to 10
            if (n < 100000000)
                return 8;
            else {
                // 9 or 10
                if (n < 1000000000)
                    return 9;
                else
                    return 10;
            }
        }
    }

बेंचमार्क (जेवीएम वार्म-अप के बाद) - बेंचमार्क कैसे चलाया जाता है यह देखने के लिए नीचे कोड देखें:

  1. आधार रेखा विधि (String.length के साथ): 2145ms
  2. log10 विधि: 711ms = 3.02 बेसलाइन जितनी तेजी से
  3. बार-बार विभाजित: 2797ms = 0.77 बार आधारभूत रूप में तेज़
  4. विभाजन और जीत: 74ms = 28.99
    बार आधारभूत रूप में तेजी से

पूर्ण कोड:

public static void main(String[] args)
throws Exception
{

    // validate methods:
    for (int i = 0; i < 1000; i++)
        if (method1(i) != method2(i))
            System.out.println(i);
    for (int i = 0; i < 1000; i++)
        if (method1(i) != method3(i))
            System.out.println(i + " " + method1(i) + " " + method3(i));
    for (int i = 333; i < 2000000000; i += 1000)
        if (method1(i) != method3(i))
            System.out.println(i + " " + method1(i) + " " + method3(i));
    for (int i = 0; i < 1000; i++)
        if (method1(i) != method4(i))
            System.out.println(i + " " + method1(i) + " " + method4(i));
    for (int i = 333; i < 2000000000; i += 1000)
        if (method1(i) != method4(i))
            System.out.println(i + " " + method1(i) + " " + method4(i));

    // work-up the JVM - make sure everything will be run in hot-spot mode
    allMethod1();
    allMethod2();
    allMethod3();
    allMethod4();

    // run benchmark
    Chronometer c;

    c = new Chronometer(true);
    allMethod1();
    c.stop();
    long baseline = c.getValue();
    System.out.println(c);

    c = new Chronometer(true);
    allMethod2();
    c.stop();
    System.out.println(c + " = " + StringTools.formatDouble((double)baseline / c.getValue() , "0.00") + " times as fast as baseline");

    c = new Chronometer(true);
    allMethod3();
    c.stop();
    System.out.println(c + " = " + StringTools.formatDouble((double)baseline / c.getValue() , "0.00") + " times as fast as baseline");

    c = new Chronometer(true);
    allMethod4();
    c.stop();
    System.out.println(c + " = " + StringTools.formatDouble((double)baseline / c.getValue() , "0.00") + " times as fast as baseline");
}


private static int method1(int n)
{
    return Integer.toString(n).length();
}
private static int method2(int n)
{
    if (n == 0)
        return 1;
    return (int)(Math.log10(n) + 1);
}
private static int method3(int n)
{
    if (n == 0)
        return 1;
    int l;
    for (l = 0 ; n > 0 ;++l)
        n /= 10;
    return l;
}
private static int method4(int n)
{
    if (n < 100000)
    {
        // 5 or less
        if (n < 100)
        {
            // 1 or 2
            if (n < 10)
                return 1;
            else
                return 2;
        }
        else
        {
            // 3 or 4 or 5
            if (n < 1000)
                return 3;
            else
            {
                // 4 or 5
                if (n < 10000)
                    return 4;
                else
                    return 5;
            }
        }
    }
    else
    {
        // 6 or more
        if (n < 10000000)
        {
            // 6 or 7
            if (n < 1000000)
                return 6;
            else
                return 7;
        }
        else
        {
            // 8 to 10
            if (n < 100000000)
                return 8;
            else
            {
                // 9 or 10
                if (n < 1000000000)
                    return 9;
                else
                    return 10;
            }
        }
    }
}


private static int allMethod1()
{
    int x = 0;
    for (int i = 0; i < 1000; i++)
        x = method1(i);
    for (int i = 1000; i < 100000; i += 10)
        x = method1(i);
    for (int i = 100000; i < 1000000; i += 100)
        x = method1(i);
    for (int i = 1000000; i < 2000000000; i += 200)
        x = method1(i);

    return x;
}
private static int allMethod2()
{
    int x = 0;
    for (int i = 0; i < 1000; i++)
        x = method2(i);
    for (int i = 1000; i < 100000; i += 10)
        x = method2(i);
    for (int i = 100000; i < 1000000; i += 100)
        x = method2(i);
    for (int i = 1000000; i < 2000000000; i += 200)
        x = method2(i);

    return x;
}
private static int allMethod3()
{
    int x = 0;
    for (int i = 0; i < 1000; i++)
        x = method3(i);
    for (int i = 1000; i < 100000; i += 10)
        x = method3(i);
    for (int i = 100000; i < 1000000; i += 100)
        x = method3(i);
    for (int i = 1000000; i < 2000000000; i += 200)
        x = method3(i);

    return x;
}
private static int allMethod4()
{
    int x = 0;
    for (int i = 0; i < 1000; i++)
        x = method4(i);
    for (int i = 1000; i < 100000; i += 10)
        x = method4(i);
    for (int i = 100000; i < 1000000; i += 100)
        x = method4(i);
    for (int i = 1000000; i < 2000000000; i += 200)
        x = method4(i);

    return x;
}

फिर, बेंचमार्क:

  1. आधार रेखा विधि (String.length के साथ): 2145ms
  2. log10 विधि: 711ms = 3.02 बेसलाइन जितनी तेजी से
  3. बार-बार विभाजित: 2797ms = 0.77 बार आधारभूत रूप में तेज़
  4. विभाजन और जीत: 74ms = 28.99
    बार आधारभूत रूप में तेजी से

संपादित करें: बेंचमार्क लिखने के बाद, मैंने Java 6 से Integer.toString में एक चुपके चोटी ली, और मैंने पाया कि यह इस प्रकार है:

final static int [] sizeTable = { 9, 99, 999, 9999, 99999, 999999, 9999999,
                                  99999999, 999999999, Integer.MAX_VALUE };

// Requires positive x
static int stringSize(int x) {
    for (int i=0; ; i++)
        if (x <= sizeTable[i])
            return i+1;
}

मैंने इसे अपने विभाजन और जीत के समाधान के खिलाफ बेंचमार्क किया:

  1. फूट डालो और जीतो: 104ms
  2. जावा 6 समाधान - पुनरावृति और तुलना: 406ms

मेरा जावा 4 समाधान के रूप में उपवास के बारे में 4x है।


7
यह बहुत अच्छा लग रहा है। आप इसे और अधिक कॉम्पैक्ट का उपयोग कर लिख सकते हैं ?: ऑपरेटर को और अधिक स्वीकृति प्राप्त करने के लिए
एंड्रे पेरेसिस

88
समय से पहले अनुकूलन के बारे में बात करें: डी
गॉर्डन गुस्ताफसन

2
मुझें यह पसंद है! कैसे के बजाय एक स्विच ब्लॉक के बजाय नेस्टेड-अगर है?
केबमैन

2
मैं इन सब का एहसास नहीं था अगर बयान बयान करने के लिए स्ट्रिंग परिवर्तित करने की तुलना में बहुत तेजी से होगा तो .length। +1
ओगन

15
टर्नरी ऑपरेटर का उपयोग करके, इसे 101 वर्णों तक लाया जाता है:n<100000?n<100?n<10?1:2:n<1000?3:n<10000?4:5:n<10000000?n<1000000?6:7:n<100000000?8:n<1000000000?9:10
जोनाथन गवरीच

13

आपके बेंचमार्क पर दो टिप्पणियाँ: जावा एक जटिल वातावरण है, जो कि केवल-इन-टाइम संकलन और कचरा संग्रह के साथ है और इसके आगे, इसलिए उचित तुलना प्राप्त करने के लिए, जब भी मैं बेंचमार्क चलाता हूं, मैं हमेशा: (ए) दो परीक्षणों को संलग्न करता हूं एक लूप में जो उन्हें 5 या 10 बार अनुक्रम में चलाता है। काफी बार लूप के माध्यम से दूसरे पास पर रनटाइम पहले से काफी अलग है। और (बी) प्रत्येक "दृष्टिकोण" के बाद, मैं एक कचरा संग्रह को ट्रिगर करने का प्रयास करने के लिए एक System.gc () करता हूं। अन्यथा, पहला दृष्टिकोण वस्तुओं का एक समूह उत्पन्न कर सकता है, लेकिन कूड़े के संग्रह को मजबूर करने के लिए पर्याप्त नहीं है, फिर दूसरा दृष्टिकोण कुछ वस्तुओं को बनाता है, ढेर समाप्त हो जाता है, और कचरा संग्रह चलता है। फिर पहले दृष्टिकोण द्वारा छोड़े गए कचरे को उठाने के लिए दूसरा दृष्टिकोण "चार्ज" किया जाता है। बहुत अनुचित!

उस ने कहा, न तो ऊपर इस उदाहरण में एक महत्वपूर्ण अंतर है।

उन संशोधनों के साथ या बिना, मुझे आपके द्वारा किए गए परिणामों की तुलना में बहुत भिन्न परिणाम मिले। जब मैंने इसे चलाया, हाँ, तोस्ट्रिंग दृष्टिकोण ने 6400 से 6600 मिली तक का समय दिया, जबकि लॉग दृष्टिकोण 20,000 से 20,400 मिलिस तक था। थोड़ा तेज होने के बजाय, लॉग दृष्टिकोण मेरे लिए 3 गुना धीमा था।

ध्यान दें कि दो दृष्टिकोणों में बहुत भिन्न लागतें शामिल होती हैं, इसलिए यह पूरी तरह से चौंकाने वाला नहीं है: स्ट्रिंग दृष्टिकोण बहुत अधिक अस्थायी वस्तुओं का निर्माण करेगा, जिन्हें साफ करना होगा, जबकि लॉग दृष्टिकोण अधिक गहन गणना लेता है। तो शायद अंतर यह है कि कम मेमोरी वाली मशीन पर, स्ट्रींग में अधिक कचरा संग्रह राउंड की आवश्यकता होती है, जबकि धीमी प्रोसेसर वाली मशीन पर, लॉग की अतिरिक्त गणना अधिक दर्दनाक होगी।

मैंने तीसरा तरीका भी आजमाया। मैंने यह छोटा सा समारोह लिखा है:

static int numlength(int n)
{
    if (n == 0) return 1;
    int l;
    n=Math.abs(n);
    for (l=0;n>0;++l)
        n/=10;
    return l;           
}

यह 1600 से 1900 मिली-दौड़ा था, जो स्ट्रींग अप्रोच के 1/3 से कम था, और मेरी मशीन पर लॉग एप्रोच 1/10 था।

यदि आपके पास संख्याओं की एक विस्तृत श्रृंखला थी, तो आप लूप के माध्यम से समय की संख्या को कम करने के लिए 1,000 या 1,000,000 से विभाजित करके शुरू करके इसे और गति दे सकते हैं। मैंने उसके साथ नहीं खेला है।


क्या आपने इनपुट अलग-अलग करने की कोशिश की है? हॉटस्पॉट VM गलत ग्राफ़ के परिणामस्वरूप, अन्यथा इस ग्राफ़ को अनुकूलित कर सकता है, क्योंकि यह हर बार एक ही पूर्वनिर्मित चीज़ को लौटा रहा है।
एरिक एगर

11

जावा का उपयोग करना

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

import java.lang.Math.*;शुरुआत में उपयोग करें

C का उपयोग करना

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

inclue math.hशुरुआत में उपयोग करें


1
सिर्फ FYI करें, यदि परिणाम the_integerहै 0, तो अनंतता होगी , इसलिए उसके लिए जाँच करें।
एरिक एगर

9

अभी तक एक टिप्पणी नहीं छोड़ सकता, इसलिए मैं एक अलग उत्तर के रूप में पोस्ट करूंगा।

लघुगणक-आधारित समाधान बहुत बड़े लंबे पूर्णांक के लिए अंकों की सही संख्या की गणना नहीं करता है, उदाहरण के लिए:

long n = 99999999999999999L;

// correct answer: 17
int numberOfDigits = String.valueOf(n).length();

// incorrect answer: 18
int wrongNumberOfDigits = (int) (Math.log10(n) + 1); 

लघुगणक-आधारित समाधान बड़े पूर्णांकों में अंकों की गलत संख्या की गणना करता है


try (int) (Math.log10 (n + j)) बजाय j जहां 10 - (n - n / 10 * 10) है।
एरिक स्टोन

8

चूंकि किसी पूर्णांक के आधार 10 में अंकों की संख्या सिर्फ 1 + ट्रंकट (लॉग 10 (संख्या)) है , आप यह कर सकते हैं:

public class Test {

    public static void main(String[] args) {

        final int number = 1234;
        final int digits = 1 + (int)Math.floor(Math.log10(number));

        System.out.println(digits);
    }
}

संपादित किया गया क्योंकि मेरे अंतिम संपादन ने कोड उदाहरण को निर्धारित किया, लेकिन विवरण नहीं।


ठंडा। लेकिन मुझे लगता है कि इसे एब्स (संख्या) की आवश्यकता है और "0" भी विशेष मामला है?
दिमित्री

हाँ। आप हस्ताक्षर के लिए खाते की जरूरत है, तो आप की तरह कुछ करना होगा 1 + (int) Math.floor (Math.log10 (Math.abs (संख्या))) + (? (संख्या <0) 1: 0)
डिर्क

5
Math.floorथोड़ा निरर्थक है, है ना? intवैसे भी इसे नीचे करने के लिए कास्टिंग करना ।
CompuChip

5

अगर किसी को कॉपी और पेस्ट करना है तो मैरिएन का समाधान लंबी टाइप संख्या (9,223,372,036,854,775,807 तक) के लिए अनुकूलित है। कार्यक्रम में मैंने 10000 तक की संख्याओं के लिए यह लिखा था, बहुत अधिक संभावित थे, इसलिए मैंने उनके लिए एक विशिष्ट शाखा बनाई। वैसे भी इससे कोई फर्क नहीं पड़ेगा।

public static int numberOfDigits (long n) {     
    // Guessing 4 digit numbers will be more probable.
    // They are set in the first branch.
    if (n < 10000L) { // from 1 to 4
        if (n < 100L) { // 1 or 2
            if (n < 10L) {
                return 1;
            } else {
                return 2;
            }
        } else { // 3 or 4
            if (n < 1000L) {
                return 3;
            } else {
                return 4;
            }
        }           
    } else  { // from 5 a 20 (albeit longs can't have more than 18 or 19)
        if (n < 1000000000000L) { // from 5 to 12
            if (n < 100000000L) { // from 5 to 8
                if (n < 1000000L) { // 5 or 6
                    if (n < 100000L) {
                        return 5;
                    } else {
                        return 6;
                    }
                } else { // 7 u 8
                    if (n < 10000000L) {
                        return 7;
                    } else {
                        return 8;
                    }
                }
            } else { // from 9 to 12
                if (n < 10000000000L) { // 9 or 10
                    if (n < 1000000000L) {
                        return 9;
                    } else {
                        return 10;
                    }
                } else { // 11 or 12
                    if (n < 100000000000L) {
                        return 11;
                    } else {
                        return 12;
                    }
                }
            }
        } else { // from 13 to ... (18 or 20)
            if (n < 10000000000000000L) { // from 13 to 16
                if (n < 100000000000000L) { // 13 or 14
                    if (n < 10000000000000L) { 
                        return 13;
                    } else {
                        return 14;
                    }
                } else { // 15 or 16
                    if (n < 1000000000000000L) {
                        return 15;
                    } else {
                        return 16;
                    }
                }
            } else { // from 17 to ...¿20?
                if (n < 1000000000000000000L) { // 17 or 18
                    if (n < 100000000000000000L) {
                        return 17;
                    } else {
                        return 18;
                    }
                } else { // 19? Can it be?
                    // 10000000000000000000L is'nt a valid long.
                    return 19;
                }
            }
        }
    }
}

क्या इस प्रश्न का शीर्षक "इंट / लॉन्ग में अंकों की संख्या प्राप्त करने के लिए" बदला जाना चाहिए? (और 'लॉन्ग' टैग जोड़ा गया है)
JAIL

4

एक और स्ट्रिंग दृष्टिकोण। छोटा और मीठा - किसी भी पूर्णांक के लिए n

int length = ("" + n).length();

केवल सकारात्मक पूर्णांक nऔर शून्य के लिए काम करता है। ("" + Math.abs(n)).length()ऋणात्मक पूर्णांक की लंबाई प्राप्त करने के लिए उपयोग कर सकते हैं ।
ThisClark

3

क्या मैं कोशिश कर सकता हूं? ;)

डिर्क के समाधान पर आधारित है

final int digits = number==0?1:(1 + (int)Math.floor(Math.log10(Math.abs(number))));

3

सादे पुराने गणित के बारे में कैसे? 0 तक पहुंचने तक 10 से विभाजित करें।

public static int getSize(long number) {
        int count = 0;
        while (number > 0) {
            count += 1;
            number = (number / 10);
        }
        return count;
    }

1
क्या आपने इसका परीक्षण किया है? आप जानते हैं कि, यह मानवीय दृष्टिकोण के लिए भी कठिन है, यह वास्तव में मशीन की "सोच-विचार" के साथ ही काम नहीं करता है, है ना? --- मुझे एक बात का प्रस्ताव दें: दो मिलियन संख्याओं की एक सरणी बनाएं, अधिमानतः Long.MAX_VALUE, जो आपके कोड की सबसे खराब जटिलता का मामला है, और System.nanoTime()दूसरे समाधान के सबसे खराब जटिलता वाले मामलों के खिलाफ क्लॉकिंग ट्रायल करने के लिए उपयोग करें। ++ वास्तव में, यह की श्रृंखला के लिए एक randomizer सेट द्वारा भरा एक सरणी के साथ प्रयास 0करने के लिए Long.MAX_VALUEभी, बस "औसत जटिलता" परीक्षण ++ आप परिणामों मिल सकती है ... बहुत चौंकाने के लिए।
XenoRo

@thelima यह शून्य या नकारात्मक के लिए सही ढंग से काम नहीं करता है, लेकिन यह एक मामूली बग है। सिद्धांत मुझे सही लगता है। क्या "चौंकाने वाला" परिणाम आप का उल्लेख कर रहे हैं?
Jay

चलो बस कंप्यूटर कहते हैं कि ... ठीक है ... वे विभाजित करना पसंद नहीं करते हैं। और ऐसे मामलों में जहां बड़ी संख्या में बड़ी "कतारों" को संसाधित करने की आवश्यकता होती है, और प्रत्येक संसाधित संख्या में प्रत्येक अंक को एक विभाजन की आवश्यकता होगी ... खैर ... चीजें "वास्तव में बहुत तेजी से धीमी गति से शुरू हो रही हैं" ... यदि आप मेरी पकड़ लेते हैं अर्थ ... --- यही कारण है कि आप यहाँ कई उत्तरों को कोडों के आधार पर परीक्षण के आधार पर देखते हैं और प्रत्येक दशमलव अंकों के साथ तुलना करते हैं, 'यदि है, तो विभाजनों के बजाय: यदि इसका उपयोग तेज नहीं है, तो कम से कम यह इसकी परवाह किए बिना अधिकांश गति को बनाए रखता है। यह सबसे बुरा मामला है। --- बड़ी संख्या में विभाजनों और लघुगणक का उपयोग करने के बीच एक परीक्षण करें ...
XenoRo

@ लीमा तुम किस बारे में बात कर रही हो? int,इस लूप के लिए अधिकतम 11 बार निष्पादित किया जाता है। क्या आपके पास अपने दावे के लिए कुछ सबूत हैं?
लोर्न

@EJP एक हार्डवेयर दृष्टिकोण से, विभाजन एक पुनरावृत्त प्रक्रिया है। सबसे तेज़ डिवीज़न एल्गोरिथ्म जो मुझे पता है कि मूलांक 4 है, जो प्रति चक्कर 4 बिट उत्पन्न करता है; इसलिए 32 बिट के विभाजन में कम से कम 8 पुनरावृत्तियों की आवश्यकता होती है। उदाहरण के लिए, गुणा, समानांतर में किया जा सकता है, और सरल गुणन में भी टूट सकता है; या तो बिट स्तर तक (केवल 5 संचालन की आवश्यकता है), या आंशिक विराम के साथ-साथ अंत में एक लुक-अप तालिका (क्लासिक आकार वीएस गति व्यापार-बंद)। यह "कितने पुनरावृत्तियों" के बारे में नहीं है; विभाजनों के साथ समस्या "हार्डवेयर स्तर पर प्रत्येक पुनरावृत्ति का क्या अर्थ है / करता है"
XenoRo

2

मैरियन का समाधान, अब टेरनेरी के साथ:

 public int len(int n){
        return (n<100000)?((n<100)?((n<10)?1:2):(n<1000)?3:((n<10000)?4:5)):((n<10000000)?((n<1000000)?6:7):((n<100000000)?8:((n<1000000000)?9:10)));
    }

क्योंकि हम कर सकते हैं।


2
यह थोड़े मुश्किल है। शायद कुछ रिक्त स्थान और / या नई लिंक जोड़ें।
michaelb958 - GoFundMonica

लेकिन लानत है यह पोर्टेबल!
ट्रेवर रुडोल्फ

1

उत्सुक, मैंने इसे बेंचमार्क करने की कोशिश की ...

import org.junit.Test;
import static org.junit.Assert.*;


public class TestStack1306727 {

    @Test
    public void bench(){
        int number=1000;
        int a= String.valueOf(number).length();
        int b= 1 + (int)Math.floor(Math.log10(number));

        assertEquals(a,b);
        int i=0;
        int s=0;
        long startTime = System.currentTimeMillis();
        for(i=0, s=0; i< 100000000; i++){
            a= String.valueOf(number).length();
            s+=a;
        }
        long stopTime = System.currentTimeMillis();
        long runTime = stopTime - startTime;
        System.out.println("Run time 1: " + runTime);
        System.out.println("s: "+s);
        startTime = System.currentTimeMillis();
        for(i=0,s=0; i< 100000000; i++){
            b= number==0?1:(1 + (int)Math.floor(Math.log10(Math.abs(number))));
            s+=b;
        }
        stopTime = System.currentTimeMillis();
        runTime = stopTime - startTime;
        System.out.println("Run time 2: " + runTime);
        System.out.println("s: "+s);
        assertEquals(a,b);


    }
}

परिणाम हैं:

रन टाइम 1: 6765
s: 400000000
रन समय 2: 6000
s: 400000000

अब मुझे आश्चर्य है कि अगर मेरे बेंचमार्क का वास्तव में कुछ मतलब है, लेकिन मुझे बेंचमार्क के कई रनों के साथ लगातार परिणाम (एमएस के भीतर विविधताएं) मिलते हैं ... :) ऐसा लगता है कि यह कोशिश करना और इसे अनुकूलित करना बेकार है ...


संपादित करें: ptomli की टिप्पणी के बाद, मैंने उपरोक्त कोड में 'i' को 'i' से बदल दिया और बेंच के 5 रनों से अधिक के निम्नलिखित परिणाम मिले:

रन टाइम 1: 11500
s: 788888890
चलने का समय 2: 8547
s: 788888890

रन टाइम 1: 11485
s: 788888890
चलने का समय 2: 8547
s: 788888890

रन समय 1: 11469
s: 788888890
चलने का समय 2: 8547
s: 788888890

रन टाइम 1: 11500
s: 788888890
चलने का समय 2: 8547
s: 788888890

रन टाइम 1: 11484
s: 788888890
चलने का समय 2: 8547
s: 788888890

1
बस इसके मज़े के लिए, 0 से एक ट्रिलियन तक, संख्या के मूल्यों के वितरण में क्या अंतर है? :)
१५:२० बजे पितमली २०'०

0

इस पुनरावर्ती विधि के बारे में क्या?

    private static int length = 0;

    public static int length(int n) {
    length++;
    if((n / 10) < 10) {
        length++;
    } else {
        length(n / 10);
    }
    return length;
}

0

सरल उपाय:

public class long_length {
    long x,l=1,n;
    for (n=10;n<x;n*=10){
        if (x/n!=0){
            l++;
        }
    }
    System.out.print(l);
}

0

एक बहुत ही सरल उपाय:

public int numLength(int n) {
  for (int length = 1; n % Math.pow(10, length) != n; length++) {}
  return length;
}

मैं एक खाली शरीर के साथ पाश के लिए एक पंक्ति नहीं कहूंगा। न ही मोडुलो 10 की शक्ति को देखने के लिए कि क्या आपको एक ही चीज़ वापस मिलती है (क्या आप सिर्फ एक तुलना का उपयोग नहीं कर सकते?)।
तीपेमम्म 15

0

या लंबाई के बजाय आप जांच सकते हैं कि संख्या बड़ी है या छोटी है तो वांछित संख्या।

    public void createCard(int cardNumber, int cardStatus, int customerId) throws SQLException {
    if(cardDao.checkIfCardExists(cardNumber) == false) {
        if(cardDao.createCard(cardNumber, cardStatus, customerId) == true) {
            System.out.println("Card created successfully");
        } else {

        }
    } else {
        System.out.println("Card already exists, try with another Card Number");
        do {
            System.out.println("Enter your new Card Number: ");
            scan = new Scanner(System.in);
            int inputCardNumber = scan.nextInt();
            cardNumber = inputCardNumber;
        } while(cardNumber < 95000000);
        cardDao.createCard(cardNumber, cardStatus, customerId);
    }
}

}


मुझे समझ नहीं आ रहा है। ऐसा लगता है कि आप एक अलग सवाल का जवाब दे रहे हैं।
तेईपेम्म 15

0

मैंने अभी तक गुणा-आधारित समाधान नहीं देखा है। लॉगरिथम, डिविज़न, और स्ट्रिंग-आधारित समाधान लाखों परीक्षण मामलों के बजाय अनिच्छुक हो जाएंगे, इसलिए यहां एक है ints:

/**
 * Returns the number of digits needed to represents an {@code int} value in 
 * the given radix, disregarding any sign.
 */
public static int len(int n, int radix) {
    radixCheck(radix); 
    // if you want to establish some limitation other than radix > 2
    n = Math.abs(n);

    int len = 1;
    long min = radix - 1;

    while (n > min) {
        n -= min;
        min *= radix;
        len++;
    }

    return len;
}

आधार 10 में, यह काम करता है क्योंकि n अनिवार्य रूप से 9, 99, 999 की तुलना में है ... न्यूनतम 9, 90, 900 ... और n को 9, 90, 900 द्वारा घटाया जा रहा है ...

दुर्भाग्य से, यह अतिप्रवाह longके intकारण हर उदाहरण को बदलकर पोर्टेबल नहीं है । दूसरी ओर, ऐसा बस इतना होता है कि यह 2 और 10 ठिकानों के लिए काम करेगा (लेकिन अधिकांश अन्य ठिकानों के लिए बुरी तरह से विफल है)। आप अतिप्रवाह अंक (या एक विभाजन परीक्षण ... ईडब्ल्यू) के लिए एक खोज तालिका की आवश्यकता होगी

/**
 * For radices 2 &le r &le Character.MAX_VALUE (36)
 */
private static long[] overflowpt = {-1, -1, 4611686018427387904L,
    8105110306037952534L, 3458764513820540928L, 5960464477539062500L,
    3948651115268014080L, 3351275184499704042L, 8070450532247928832L,
    1200757082375992968L, 9000000000000000000L, 5054470284992937710L,
    2033726847845400576L, 7984999310198158092L, 2022385242251558912L,
    6130514465332031250L, 1080863910568919040L, 2694045224950414864L,
    6371827248895377408L, 756953702320627062L, 1556480000000000000L,
    3089447554782389220L, 5939011215544737792L, 482121737504447062L,
    839967991029301248L, 1430511474609375000L, 2385723916542054400L,
    3902460517721977146L, 6269893157408735232L, 341614273439763212L,
    513726300000000000L, 762254306892144930L, 1116892707587883008L,
    1617347408439258144L, 2316231840055068672L, 3282671350683593750L,
    4606759634479349760L};

public static int len(long n, int radix) {
    radixCheck(radix);
    n = abs(n);

    int len = 1;
    long min = radix - 1;
    while (n > min) {
        len++;
        if (min == overflowpt[radix]) break;
        n -= min;
        min *= radix;

    }

    return len;
}

0

डिजाइन के साथ (समस्या पर आधारित)। यह फूट डालो और जीतो का एक पर्याय है। हम पहले एक एनम को परिभाषित करेंगे (यह केवल एक अहस्ताक्षरित इंट के लिए)।

public enum IntegerLength {
    One((byte)1,10),
    Two((byte)2,100),
    Three((byte)3,1000),
    Four((byte)4,10000),
    Five((byte)5,100000),
    Six((byte)6,1000000),
    Seven((byte)7,10000000),
    Eight((byte)8,100000000),
    Nine((byte)9,1000000000);

    byte length;
    int value;

    IntegerLength(byte len,int value) {
        this.length = len;
        this.value = value;
    }

    public byte getLenght() {
        return length;
    }

    public int getValue() {
        return value;
    }
}

अब हम एक ऐसे वर्ग को परिभाषित करेंगे जो एनम के मूल्यों से गुजरता है और तुलना करता है और उपयुक्त लंबाई देता है।

public class IntegerLenght {
    public static byte calculateIntLenght(int num) {    
        for(IntegerLength v : IntegerLength.values()) {
            if(num < v.getValue()){
                return v.getLenght();
            }
        }
        return 0;
    }
}

इस समाधान का रन टाइम डिवाइड-एंड-कॉनकेयर दृष्टिकोण के समान है।


एक विभाजन और जीत के बीच में शुरू होता है और शेष खोज क्षेत्र bisect जाएगा। यह एक रैखिक रन समय है। लेकिन यह केवल 9 तुलनाओं के लिए मायने नहीं रखेगा। लेकिन यह गड़बड़ नहीं होगा अगर num>=Nine.getValue()?
तेईपेमम

0

एक ऐसा ज्यादातर इसलिए करना चाहता है क्योंकि वह / वह इसे "पेश" करना चाहता है, जिसका ज्यादातर मतलब यह है कि आखिरकार "स्ट्रींग-एड" (या दूसरे तरीके से रूपांतरित) को स्पष्ट रूप से या वैसे भी; प्रस्तुत करने से पहले (उदाहरण के लिए मुद्रित)।

यदि ऐसा है तो बस आवश्यक "toString" स्पष्ट करने की कोशिश करें और बिट्स की गणना करें।


0

हम एक पुनरावर्ती लूप का उपयोग करके इसे प्राप्त कर सकते हैं

    public static int digitCount(int numberInput, int i) {
        while (numberInput > 0) {
        i++;
        numberInput = numberInput / 10;
        digitCount(numberInput, i);
        }
        return i;
    }

    public static void printString() {
        int numberInput = 1234567;
        int digitCount = digitCount(numberInput, 0);

        System.out.println("Count of digit in ["+numberInput+"] is ["+digitCount+"]");
    }

0

मैंने Integer.javaसोर्स कोड देखने के बाद यह फ़ंक्शन लिखा था ।

private static int stringSize(int x) {
    final int[] sizeTable = {9, 99, 999, 9_999, 99_999, 999_999, 9_999_999,
            99_999_999, 999_999_999, Integer.MAX_VALUE};
    for (int i = 0; ; ++i) {
        if (x <= sizeTable[i]) {
            return i + 1;
        }
    }
}

0

मैं लोगों को स्ट्रिंग पुस्तकालयों का उपयोग करते हुए या यहां तक ​​कि इंटेगर वर्ग का उपयोग करते हुए देखता हूं। इसमें कुछ भी गलत नहीं है लेकिन अंकों की संख्या प्राप्त करने के लिए एल्गोरिथ्म उतना जटिल नहीं है। मैं इस उदाहरण में एक लंबे समय का उपयोग कर रहा हूं, लेकिन यह एक इंट के साथ ठीक काम करता है।

 private static int getLength(long num) {

    int count = 1;

    while (num >= 10) {
        num = num / 10;
        count++;
    }

    return count;
}

0

कोई स्ट्रिंग एपीआई, कोई बर्तन, कोई प्रकार का रूपांतरण, सिर्फ शुद्ध जावा पुनरावृत्ति ->

public static int getNumberOfDigits(int input) {
    int numOfDigits = 1;
    int base = 1;
    while (input >= base * 10) {
        base = base * 10;
        numOfDigits++;
    }
    return numOfDigits;
 }

आप कृपया बड़े मूल्यों के लिए लंबे समय तक जा सकते हैं।


-1
    int num = 02300;
    int count = 0;
    while(num>0){
         if(num == 0) break;
         num=num/10;
         count++;
    }
    System.out.println(count);

सिनिस्टा द्वारा दो साल पहले "डिवाइड बाय 10" समाधान पहली बार पोस्ट किया गया था।
तेईपेम्म डे

-1

आसान पुनरावर्ती तरीका

int    get_int_lenght(current_lenght, value)
{
 if (value / 10 < 10)
    return (current_lenght + 1);
return (get_int_lenght(current_lenght + 1, value))
}

टेस्ट नहीं हुआ


3
आपको शायद तब इसका परीक्षण करना चाहिए (और सुनिश्चित करें कि यह वैध जावा और ठीक से स्वरूपित है)। लेकिन 3 साल पहले एक पुनरावर्ती "डिवाइड बाय 10" दृष्टिकोण जेडी डूला द्वारा पोस्ट किया गया था।
तेयपेमम

-2

आप दस तक क्रमिक विभाजन का उपयोग करके अंक प्राप्त कर सकते हैं:

int a=0;

if (no < 0) {
    no = -no;
} else if (no == 0) {
    no = 1;
}

while (no > 0) {
    no = no / 10;
    a++;
}

System.out.println("Number of digits in given number is: "+a);

"डिवाइड बाय 10" दृष्टिकोण को पहली बार 3 साल पहले सिनिस्टा द्वारा पोस्ट किया गया था। यही एकमात्र कारण है कि मैं सोच सकता हूं कि आपको एक गिरावट मिली।
तेयुपमेम

-2

संख्या दर्ज करें और एक बनाएं Arraylist, और जबकि लूप सभी अंकों को रिकॉर्ड करेगा Arraylist। फिर हम सरणी का आकार निकाल सकते हैं, जो आपके द्वारा दर्ज किए गए पूर्णांक मान की लंबाई होगी।

ArrayList<Integer> a=new ArrayList<>();

while(number > 0) 
{ 
    remainder = num % 10; 
    a.add(remainder);
    number = number / 10; 
} 

int m=a.size();

1
सिवाय इसके कि आपको ArrayList या अंक की आवश्यकता नहीं है।
लोर्न

-2

यहाँ एक बहुत ही सरल विधि है जो मैंने किसी भी संख्या के लिए काम की है:

public static int numberLength(int userNumber) {

    int numberCounter = 10;
    boolean condition = true;
    int digitLength = 1;

    while (condition) {
        int numberRatio = userNumber / numberCounter;
        if (numberRatio < 1) {
            condition = false;
        } else {
            digitLength++;
            numberCounter *= 10;
        }
    }

    return digitLength; 
}

जिस तरह से यह काम करता है वह संख्या काउंटर चर के साथ है कि 10 = 1 अंक का स्थान है। उदाहरण के लिए .1 = 1 दसवां => 1 अंक का स्थान। इसलिए यदि आपके पास int number = 103342;6 हैं, क्योंकि यह .000001 रिक्त स्थान के बराबर है। इसके अलावा, किसी के लिए एक बेहतर चर नाम है numberCounter? मैं कुछ भी बेहतर नहीं सोच सकता।

संपादित करें: बस एक बेहतर स्पष्टीकरण के बारे में सोचा। अनिवार्य रूप से लूप करते समय यह क्या कर रहा है ताकि आप अपनी संख्या को 10 से विभाजित करें, जब तक कि यह एक से कम न हो। अनिवार्य रूप से, जब आप 10 से कुछ विभाजित करते हैं, तो आप इसे एक नंबर स्थान पर वापस ले जाते हैं, इसलिए आप इसे 10 तक विभाजित करते हैं जब तक कि आप अपने नंबर में अंकों की मात्रा के लिए <1 तक नहीं पहुंच जाते।

यहाँ एक और संस्करण है जो एक दशमलव में संख्याओं की संख्या को गिन सकता है:

public static int repeatingLength(double decimalNumber) {

    int numberCounter = 1;
    boolean condition = true;
    int digitLength = 1;

    while (condition) {
        double numberRatio = decimalNumber * numberCounter;

        if ((numberRatio - Math.round(numberRatio)) < 0.0000001) {
            condition = false;
        } else {
            digitLength++;
            numberCounter *= 10;
        }
    }
    return digitLength - 1;
}

-3

परिवर्तित करने का प्रयास करें पूर्णांक एक करने के लिए स्ट्रिंग और उसके बाद की लंबाई मिल स्ट्रिंग । कि इंट की लंबाई मिलनी चाहिए ।

public static int intLength(int num){
    String n = Integer.toString(num);
    int newNum = n.length();
    return newNum;
}

यह मूल कोड के पूरी तरह से बराबर है। और numberनकारात्मक होने पर चूक जाएगा ।
तेईपेम्म 15
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.