簡體   English   中英

如何比較大字符串整數值

[英]How to compare large string integer values

目前,我正在開發一個處理極大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/zh-cn/library/system.numerics.biginteger.aspx )大小。

如果您不相信我,請運行此代碼

        var foo = new BigInteger(2);


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

事情變得瘋狂。 我的調試器(VS2013)在完成之前無法表示該數字。 運行了很短的時間,並從ToString得到一個以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即放棄精度並存儲尾數和指數。 如果您看一下浮點數是如何實現的,它們就不能代表其最大值和最小值之間的所有數字(因為范圍內的實數比無限大)。 它們在精度和范圍之間進行了復雜的權衡。 如果您想這樣做,那么與考慮像Biginteger這樣的整數表示形式相比,查看float實現會有用得多。

暫無
暫無

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

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