سؤال

من السهل إلى حد ما، إذا كان رقم biginterger هو 543 أريده أن يقطع الرقم الأخير بحيث يكون 54.

يمكن أن يكون سهلا سهلا للقيام بذلك:

  1. استخدم السلاسل، واحصل على فرعية وإنشاء Biginteger جديد بالقيمة الجديدة.
  2. استخدام طريقة تقسيم bigintegers مع الرقم 10. (543/10 = 54.3 => 54)

الشيء هو أنني سوف أدفع هذا كثير من المرات مع أعداد صحيحة كبيرة بالطبع.

تخميني هو أن اللعب مع سلاسل سيكون أبطأ ولكن مرة أخرى لم أستخدم bigintegers كثيرا وليس لدي فكرة عن مدى أهمية عملية "الفجوة".

السرعة ضرورية هنا، ما هي أسرع طريقة لتنفيذ هذا (الذاكرة ليست مشكلة فقط السرعة)؟

حلول أخرى هي أيضا موضع ترحيب.

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

المحلول

تقسيم 10 أسرع بكثير من استخدام عملية فرعية. باستخدام المعيار التالي، أحصل على حوالي 161x مرات (نسبة تتناسب مع عدد قليل)

    long divTime = 0;
    long substrTime = 0;
    final int bitsCount = 1000;

    for (int i = 0; i < 1000; ++i) {
        long t1, t2;
        BigInteger random = new BigInteger(bitsCount, new Random());

        t1 = System.currentTimeMillis();
        random.divide(BigInteger.TEN);
        t2 = System.currentTimeMillis();
        divTime += (t2 - t1);

        t1 = System.currentTimeMillis();
        String str = random.toString();
        new BigInteger(str.substring(0, str.length() - 1));
        t2 = System.currentTimeMillis();
        substrTime += (t2 - t1);
    }

    System.out.println("Divide: " + divTime);
    System.out.println("Substr: " + substrTime);
    System.out.println("Ratio:  " + (substrTime / divTime));

نصائح أخرى

الفجوة بنسبة 10 من المرجح أن يكون أسرع.

إذا قمت بإنشاء biginteregers، فإن الرقم 10، ثم استخدم ذلك للتقسيم بحلول 10، سيكون من المحتمل أن تكون أسرع طريقة للقيام بذلك. إنه يدق إنشاء مبينجر جديد مؤقت في كل مرة.

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

أسرع طريقة تقسيم الرقم بحلول 10 مع تنفيذ التقسيم الداخلي الفعال. إن تناول هذه العملية وراء الكواليس ولكن بالتأكيد غير تافهة نظرا لأن الرقم يتم تخزينه Base-2.

من المحتمل أن يستخدم أسرع التنفيذ الممكن من نوع بيانات يستخدم التمثيل الداخلي قاعدة 10، أي نوع من BCD.. وبعد ثم، فإن التقسيم بحلول 10 سيعني ببساطة إسقاط البايت الأخير (أو حتى مجرد زيادة / تنقذية مؤشر إذا قمت بتنفيذها بالطريقة الصحيحة).

بالطبع، يجب عليك تنفيذ جميع العمليات الحسابية وغيرها التي تحتاجها من الصفر، مما يجعل هذا العمل كثيرا.

من المحتمل أن يكون من السابق لأوانه أن يسأل هذا السؤال. افعلها الطريقة الواضحة (تقسيمها إلى عشرة)، ثم معززها، وتحسينه إذا كنت بحاجة إلى ذلك. التحويل إلى تمثيل السلسلة والعودة سيكون أبطأ بكثير.

The Tostring () وحده ربما أبطأ من السلسلة الفرعية.

قال مختلف الناس إن تقسيم 10 سيكون أسرع من التحويل إلى سلسلة وأخذ فرعية. لفهم السبب، فقط فكر في الحساب المتورط في التحويل من Biginteger إلى سلسلة، والعكس صحيح. علي سبيل المثال:

/* simplified pseudo code for converting +ve numbers to strings */
StringBuffer sb = new StringBuffer(...);
while (number != 0) {
   digit = number % 10;
   sb.append((char)(digit + '0'));
   number = number / 10;
}
return sb.toString();

الشيء المهم الإشارة إليه هو أن التحويل من عدد إلى سلسلة يستلزم تقسيم مرارا وتكرارا بنسبة 10. في الواقع عدد الأقسام يتناسب مع log10 (رقم). يحدث في الاتجاه الآخر ينطوي على تضاعفات Log10 (عدد). يجب أن يكون من الواضح أن هذا حساب أكثر بكثير من تقسيم واحد بنسبة 10.

إذا كان الأداء أمرا حاسما ... لا تستخدم جافا

في اللغات التي تجميعها إلى رمز الجهاز (على سبيل المثال C أو C ++)، يكون الفجوة الصحيحة أسرع من خلال عامل ضخم. استخدام عمليات السلسلة (أو يمكن استخدامها) مخصصات الذاكرة وبالتالي فهي بطيئة.

أراهن هو أنه في أقسام Java Int سيكون أسرع أيضا. وإلا فإن تنفيذ VM الخاص بهم غريب حقا.

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