繁体   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