目前我正在开发一个处理极大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
答案 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这样的整数表示更有用。