如何知道一个值溢出而不重复出现在运行时OverflowException中
本文关键字:OverflowException 运行时 何知道 溢出 一个 | 更新日期: 2023-09-27 18:23:48
所以问题是:
给定一个表示给定编译器(语言?)中可能的最大数字的本机积分类型,例如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.
像这样的东西算是一个解决方案吗?
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");
编译器很可能一次只解析输入的一位数字,其代码与ulong.Parse
类似,但显然适用于任务。
ulong.Parse
决定其溢出的方式相当简单,但您确实需要知道整数是如何解析的。CCD_ 8一次解析输入的一个字符。它保持ulong
的结果,对于每个字符,它将结果乘以10,然后将字符的值相加(从0到9),并一直这样做,直到输入用完或结果溢出。
有两种溢出检查,因为有两种东西可以溢出:乘10和加法。为了检查乘法运算是否溢出,将当前结果与1844674407370955161
进行比较。如果结果大于该值,并且还剩下数字,则算法退出,报告溢出。观察这个数字与去掉最后一位的ulong.MaxValue
相同,使其成为可以乘以10而不溢出的最大整数。
接下来,它需要检查从0到9的数字相加是否会溢出。它首先将数字相加,然后检查结果是否减少而不是增加。这是因为加法是如何在CPU内部实现的;基本上,结果的顶部被丢弃,因为它不适合。
就这样,真的。如果字符用完而没有触发上面两个检查中的任何一个,则数字解析成功,否则就是溢出。