如何比较大字符串整数值

本文关键字:字符串 整数 比较 何比较 | 更新日期: 2023-09-27 17:57:32

目前我正在开发一个处理超大integer数字的程序。

为了防止命中intiger.maxvalue,一个将字符串处理为数字并按照将其拆分为List<int>的脚本

0是当前已知的最高值

  • 列表条目0:123(亿二千三百万)
  • 列表条目1:321(叁拾贰万壹仟元整)
  • 列表条目2:777

现在我的问题是:如何从这些值中检查传入的字符串值是否是可处理的?

我目前做减法的开始如下,但我一直在做减法。

public bool Subtract(string value)
{
    string cleanedNumeric = NumericAndSpaces(value);
    List<string> input = new List<string>(cleanedNumeric.Split(' '));
    // In case 1) the amount is bigger 2) biggest value exceeded by a 10 fold 
    // 3)  biggest value exceeds the value
    if (input.Count > values.Count ||
        input[input.Count - 1].Length > values[0].ToString().Length ||
        FastParseInt(input[input.Count -1]) > values[0])
        return false;
    // Flip the array for ease of comparison
    input.Reverse();
    return true;
}

编辑该程序中可实现的最高数量的当前目标是Googolplex,并且限制为.net3.5 MONO

如何比较大字符串整数值

您应该对此进行一些测试,因为我还没有进行过广泛的测试,但它已经对我所经历的案例起到了作用。此外,可能值得确保字符串中的每个字符都是真正有效的整数,因为此过程会轰炸给定的非整数字符。最后,它期望减数和被减数都是正数。

    static void Main(string[] args)
    {
        // In subtraction, a subtrahend is subtracted from a minuend to find a difference.
        string minuend = "900000";
        string subtrahend = "900001";
        var isSubtractable = IsSubtractable(subtrahend, minuend);
    }
    public static bool IsSubtractable(string subtrahend, string minuend)
    {
        minuend = minuend.Trim();
        subtrahend = subtrahend.Trim();
        // maybe loop through characters and ensure all are valid integers
        // check if the original number is longer - clearly subtractable
        if (minuend.Length > subtrahend.Length) return true;
        // check if original number is shorter - not subtractable
        if (minuend.Length < subtrahend.Length) return false;
        // at this point we know the strings are the same length, so we'll
        // loop through the characters, one by one, from the start, to determine
        // if the minued has a higher value character in a column of the number.
        int numberIndex = 0;
        while (numberIndex < minuend.Length )
        {
            Int16 minuendCharValue = Convert.ToInt16(minuend[numberIndex]);
            Int16 subtrahendCharValue = Convert.ToInt16(subtrahend[numberIndex]);
            if (minuendCharValue > subtrahendCharValue) return true;
            if (minuendCharValue < subtrahendCharValue) return false;
            numberIndex++;
        }
        // number are the same
        return true;
    }

[BigInteger](https://msdn.microsoft.com/en-us/library/system.numerics.biginteger.aspx)大小不一。

如果你不相信我,运行这个代码

        var foo = new BigInteger(2);

        while (true)
        {
            foo = foo * foo;
        }

事情变得疯狂。我的调试器(VS2013)在完成之前无法表示数字。运行了一小段时间,从ToString中得到了一个以10为基数的120万位数字。它足够大了。对象有2GB的限制,可以在.NET 4.5中通过设置gcAllowVeryLargeObjects 来覆盖

现在,如果您正在使用.NET 3.5,该怎么办你基本上需要重新实现BigInteger(显然只需要你需要的,里面有很多)。

public class MyBigInteger
{
     uint[] _bits; // you need somewhere to store the value to an arbitrary length.

你还需要对这些数组进行数学运算。这是BigInteger:中的Equals方法

 public bool Equals(BigInteger other)
    {
        AssertValid();
        other.AssertValid();
        if (_sign != other._sign)
            return false;
        if (_bits == other._bits) 
            // _sign == other._sign && _bits == null && other._bits == null
            return true;
        if (_bits == null || other._bits == null)
            return false;
        int cu = Length(_bits);
        if (cu != Length(other._bits))
            return false;
        int cuDiff = GetDiffLength(_bits, other._bits, cu);
        return cuDiff == 0;
    }

它基本上对字节数组进行廉价的长度和符号比较,如果这不会产生差异,那么就交给GetDiffLength。

    internal static int GetDiffLength(uint[] rgu1, uint[] rgu2, int cu)
    {
        for (int iv = cu; --iv >= 0; )
        {
            if (rgu1[iv] != rgu2[iv])
                return iv + 1;
        }
        return 0;
    }

它执行昂贵的检查,即在数组中循环寻找差异。

所有的数学运算都必须遵循这种模式,并且可以在很大程度上从.Net源代码中剥离。

Googleplex和2GB:

在这里,2GB的限制成为了一个问题,因为您将需要3.867×10^90 GB的对象大小。这就是你放弃,或者变得聪明,并以无法代表大量对象为代价将对象存储为权力的时候*2

如果你调整你的期望值,它实际上不会改变BigInteger的数学运算,将_bits拆分为多个锯齿状数组*1。你把便宜的支票换一点。不是检查数组的大小,而是检查子数组的数量,然后检查最后一个子数组的大小。然后,循环需要稍微复杂一点(但不会复杂很多),因为它会对每个子数组进行元素数组比较。还有其他变化,但这绝不是不可能的,可以让你摆脱2GB的限制。

*1请注意,使用锯齿状数组[][],而不是多维数组[,],它们仍然受到相同的限制。

*2我放弃精度,存储尾数和指数。如果你看看浮点数是如何实现的,它们不能表示介于最大值和最小值之间的所有数字(因为一个范围内的实数数量"大于"无穷大)。它们在精度和射程之间进行复杂的权衡。如果您想这样做,那么研究float实现将比研究Biginteger之类的整数表示更有用。