[英]How to compare large string integer values
目前,我正在開發一個處理極大integer
的程序。
為了防止觸及intiger.maxvalue
以下腳本,該腳本將字符串處理為數字,然后將其拆分為List<int>
,如下所示
0是當前已知的最高值
現在我的問題是:如何檢查傳入的字符串值是否可以從這些值中減去?
我目前進行的減法開始如下,但是我陷入了減法部分。
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.