所以问题是:
给定一个本机整数类型,表示给定编译器中最大可能的数字(语言?),例如C#中的ulong
,如何检测表示数字的输入字符串将溢出最大可以由该给定类型表示的值,而不会回退到已检查的上下文和运行时OveflowException
?
显然C#编译器可以检测到常量积分溢出:
ulong l = 18446744073709551615; //ok
ulong l = 18446744073709551616; //compile time error: Integral constant is too large.
编译器是否使用了运行时OverflowException
(或等效的)?如果是这样,有没有办法实际执行此操作而不会再次出现运行时异常或构建可以容纳更大数字的数字类型,如System.Numeric.BigInt
?值得注意的是BigInt
在C#中没有本机支持,因为以下是编译时错误,尽管积分常量完全在类型的范围内:
BigInt i = 18446744073709551616; //compile time error: Integral constant is too large.
答案 0 :(得分:1)
这样的事情会算作解决方案吗?
string s1 = "18446744073709551616";
string s2 = ulong.MaxValue.ToString();
// assuming s1 contains digits only and no leading zeros
if(
s1.Length > s2.Length ||
s1.Length == s2.Length && string.CompareOrdinal(s1, s2) > 0
)
Console.WriteLine("overflow");
答案 1 :(得分:1)
编译器很可能只是一次解析输入一个数字,代码类似于ulong.Parse
,但显然适应了任务。
ulong.Parse
确定溢出的方式相当简单,但您需要知道如何解析整数。 ulong.Parse
一次解析输入的一个字符。它保持ulong
结果,并且对于每个字符,它将结果乘以10,然后添加字符的值(从0到9),并且它一直这样做,直到输入用完或结果为止溢出。
有两个溢出检查,因为有两个东西可以溢出:乘以10,加法。要检查乘法是否不会溢出,请将当前结果与1844674407370955161
进行比较。如果结果大于该值,并且仍有数字,则算法退出,报告溢出。注意这个数字与ulong.MaxValue
相同,删除了最后一个数字,使其成为最大整数,可以乘以10而不会溢出。
接下来,需要检查添加0到9之间的数字是否会溢出。它首先添加数字,然后检查结果是否减少而不是增加。这是因为在CPU内部实现了如何添加;基本上结果的最高位被丢弃,因为它不适合。
这就是它,真的。如果字符在没有跳过上述两个检查中的任何一个的情况下用完,则会成功解析该数字,否则会溢出。