如何比较大字符串整数值

时间:2015-06-20 18:54:31

标签: c# string int

目前我正在开发一个处理极大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

2 个答案:

答案 0 :(得分:1)

你应该对此进行一些测试,因为我没有进行过大量的测试,但它已经完成了我已经完成的案例。此外,可能值得确保字符串中的每个字符都是真正的有效整数,因为此过程会给出非整数字符。最后,它预计减数和减数的正数。

    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;
    }

答案 1 :(得分:1)

[BigInteger] https://msdn.microsoft.com/en-us/library/system.numerics.biginteger.aspx)的大小非常大。

如果你不相信我,请运行此代码

        var foo = new BigInteger(2);


        while (true)
        {
            foo = foo * foo;
        }
事情变得疯狂。我的调试器(VS2013)在完成之前无法表示数字。跑了很短的时间,从ToString获得了一个包含120万位数字的数字。它够大了。对象有2GB限制,可以使用设置gcAllowVeryLargeObjects

在.NET 4.5中覆盖

现在如果你使用.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 source code中扯掉。

Googleplex和2GB:

此处2GB限制成为问题,因为您需要的对象大小为3.867×10^90 gigabyte。这就是你放弃或者变得聪明并将对象存储为权力的代价,代价是无法代表它们。 * 2

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

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

* 2即放弃精度并存储尾数和指数。如果你看看如何实现浮点数,它们不能代表它们的最大值和最小值之间的所有数字(因为一个范围内的实数的数量比“无限”更大)。它们在精度和范围之间进行复杂的折衷。如果你想要这样做,那么查看float实现将比使用像Biginteger这样的整数表示更有用。