如何比较大字符串整数值
本文关键字:字符串 整数 比较 何比较 | 更新日期: 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之类的整数表示更有用。