簡體   English   中英

在C#中使剩余計數達到下一個上限10的最快方法

[英]Fastest way to get remaining count to next ceiling ten in C#

我正在執行一組非常大的數字(每個數字13位長度)的操作。

我需要用校驗和驗證每個數字。 校驗和數字將告訴它到下一個十的距離是多少,即:

checksum    checksum digit
      20                 0
      21                 9
      22                 8
      33                 7
      34                 6
      35                 5
      36                 4
      37                 3
     208                 2
       9                 1

數字為EAN-13格式。 因此,最大位數總和= 217(999999999999:無校驗和驗證)。

到目前為止,我認為最快的方法是將數據預加載到int數組中並按索引檢索。

這是最快的方法嗎?

還是在這一點上不再重要了,因為即使執行很多操作,它也將足夠快地執行?

更新:

如前所述,將cheksum的校驗和數字值預加載到數組中:

for (int i = 0; i < 220; i += 10)
{
    matchValues[i] = 0;
    matchValues[i + 1] = 9;
    matchValues[i + 2] = 8;
    matchValues[i + 3] = 7;
    matchValues[i + 4] = 6;
    matchValues[i + 5] = 5;
    matchValues[i + 6] = 4;
    matchValues[i + 7] = 3;
    matchValues[i + 8] = 2;
    matchValues[i + 9] = 1;
}

這樣,我可以用匹配的校驗和數字matchValues[sum];覆蓋所有校驗matchValues[sum];

所以:
matchValues [208] = 2;
matchValues [9] = 1;
等等

您可以使用模數來計算與天花板十的距離。 您仍然顯然需要遍歷每個數字。

int modulo = i % 10;
int distanceFromTen = modulo == 0 ? 0 : 10 - modulus;

另一個解決方案是int distanceFromTen = (int)(Math.Ceiling(i / 10d) * 10 - i);

我已經針對這兩種方法進行了基准測試:

private static void Main(string[] args)
{
    //Console.WriteLine("Checking {0}", i);

    int loops = 10;

    long averageModulo = 0;
    long averageCeiling = 0;

    for (int l = 0; l < loops; l++)
    {

        Stopwatch sw = new Stopwatch();

        sw.Start();
        for (int i = 0; i < 10000000; i++)
        {
            int modulus = i % 10;
            int distanceFromTen = modulus == 0 ? 0 : 10 - modulus;
        }
        sw.Stop();


        Stopwatch swTwo = new Stopwatch();

        swTwo.Start();

        for (int i = 0; i < 10000000; i++)
        {
            int distanceFromTenTwo = (int)(Math.Ceiling(i / 10d) * 10 - i);
        }

        swTwo.Stop();

        Console.WriteLine("Modulo:       {0} ({1}ms)", sw.ElapsedTicks, sw.ElapsedMilliseconds);

        averageModulo += sw.ElapsedTicks;

        Console.WriteLine("Math.Ceiling: {0} ({1}ms)", swTwo.ElapsedTicks, swTwo.ElapsedMilliseconds);

        averageCeiling += swTwo.ElapsedTicks;

        Console.WriteLine("");
    }

    Console.WriteLine("Average modulo:  {0}", averageModulo / loops);
    Console.WriteLine("Average ceiling: {0}", averageCeiling / loops);

    Console.ReadLine();
}

模運算始終快於上限(可能是由於拳擊)。 話雖如此,兩個操作都非常快。


我認為通過新的編輯,現在的目標是在盡可能短的時間內生成有效的EAN。 這是一些可以在3.5秒內生成000000000000 EAN-13校驗和的代碼(如Wikipedia頁面上所述)。

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

internal class Program
{
    private static void Main(string[] args)
    {
        Console.WriteLine("");

        long start = 0;
        long end = 99999999;

        long count = end - start + 1;
        long[] eans = new long[count];

        Stopwatch sw = new Stopwatch();

        sw.Start();

        Parallel.For(start, end + 1, i => {
            eans[i] = GenerateEAN13(i);
        });

        sw.Stop();

        Console.WriteLine("Generation of {0} EAN-13s took {1} ticks ({2} ms)", count, sw.ElapsedTicks, sw.ElapsedMilliseconds);

        Console.ReadLine();
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    public static long GenerateEAN13(long number)
    {
        long checksum = 0;
        long digit = 0;
        long tmp = number;

        for (int i = 13; i >= 0; i--)
        {
            digit = tmp % 10;
            tmp = tmp / 10;

            checksum += i % 2 == 0 ? digit * 3 : digit;

            if (tmp < 10)
                break;
        }

        long modulus = checksum % 10;
        checksum = modulus == 0 ? 0 : 10 - modulus;

        return number * 10 + checksum;
    }
}

為此絕對使用模數。 值的“緩存”將無濟於事,因為通過鍵查找字典值將導致減法中節省的成本,這反過來將調用GetHashCode()並產生一些開銷:

int distanceFromNextTen = (10 - input % 10) % 10;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM