此代码产生溢出错误,我不完全确定原因。这是SML,我现在对此有些不熟悉,所以我不完全确定如何解决它。
fun detPrime(num:int, divn:int) =
if divn = num
then true
else if num mod divn = 0
then false
else detPrime(num, divn+1);
fun prime(num: int) =
detPrime(num, 2);
fun goldbachHelp(num1: int, num2: int) =
if num2 > num1
then []
else if prime(num2) = true andalso prime(num1) = true
then num2::num1::[]
else goldbachHelp(num1-1, num2+1);
fun goldbach(num: int) =
if num mod 2 = 1
then []
else goldbachHelp(num, 0);
goldbach(100);
答案 0 :(得分:1)
为什么会导致溢出错误?
更重要的是,你怎么知道的?
溢出意味着整数超出Int.minInt
或Int.maxInt
的范围。你所做的就是在不同的地方增加和减少一个。所以不知何故应该最终终止这些增量和减量的条件。我稍微修改了您的代码并在其中插入了一些打印语句:
fun detPrime (num, divn) =
num = divn orelse
num mod divn <> 0 andalso
detPrime (num, divn+1)
fun isPrime num =
( print ("isPrime(" ^ Int.toString num ^ ")\n")
; detPrime (num, 2)
)
fun goldbachHelp (num1, num2) =
( print ("goldbachHelp(" ^ Int.toString num1 ^ ", " ^ Int.toString num2 ^")\n")
; if num1 > num2
then []
else if isPrime num1 andalso isPrime num2
then [num2, num1]
else goldbachHelp(num1+1, num2-1)
)
fun goldbach num =
goldbachHelp (0, num)
调用此代码会打印:
- goldbach 100;
goldbachHelp(0, 100)
isPrime(0)
goldbachHelp(1, 99)
isPrime(1)
uncaught exception Overflow [overflow]
raised at: <file stdIn>
手动评估isPrime 1
:
isPrime 1 ~> detPrime (1, 2)
~> 1 = 2 orelse 1 mod 2 <> 0 andalso detPrime (1, 2+1)
~> 1 mod 2 <> 0 andalso detPrime (1, 2+1)
~> 1 <> 0 andalso detPrime (1, 2+1)
~> detPrime (1, 3)
~> 1 = 3 orelse 1 mod 3 <> 0 andalso detPrime (1, 3+1)
~> 1 mod 3 <> 0 andalso detPrime (1, 3+1)
~> 1 <> 0 andalso detPrime (1, 3+1)
~> detPrime (1, 4)
~> 1 = 4 orelse 1 mod 4 <> 0 andalso detPrime (1, 4+1)
~> 1 mod 4 <> 0 andalso detPrime (1, 4+1)
~> 1 <> 0 andalso detPrime (1, 4+1)
~> detPrime (1, 5)
~> ... you can see where this is going ...
那么即使您可能使用合理的输入(isPrime
≥2来测试num
,因为根据定义,这是最小的素数),goldbachHelp
设法用不合理的方式调用它输入:
goldbach 100 ~> goldbachHelp (0, 100)
~> if 0 > 100
then []
else if isPrime 0 andalso isPrime 100
then [100, 0]
else goldbachHelp(0+1, 100-1)
~> if isPrime 0 andalso isPrime 100
then [100, 0]
else goldbachHelp(0+1, 100-1)
~> if detPrime (0, 2) andalso isPrime 100
then [100, 0]
else goldbachHelp(0+1, 100-1)
~> if 0 = 2 orelse
0 mod 2 <> 0 andalso
detPrime (0, 3) andalso isPrime 100
then [100, 0]
else goldbachHelp(0+1, 100-1)
~> if false orelse
false andalso
detPrime (0, 3) andalso isPrime 100
then [100, 0]
else goldbachHelp(0+1, 100-1)
~> if false andalso isPrime 100
then [100, 0]
else goldbachHelp(0+1, 100-1)
~> goldbachHelp(1, 99)
~> if 1 > 99
then []
else if isPrime 1 andalso isPrime 99
then [99, 1]
else goldbachHelp(1+1, 99-1)
~> if isPrime 1 andalso isPrime 99
then [99, 1]
else goldbachHelp(1+1, 99-1)
~> ... you can see where this is going ...
顺便提一下,isPrime 0
有效,但后续迭代中的isPrime 1
并不适用。
当问题难以找到时你可以做的事情:
插入print语句以找到计算偏离的点。
彻底测试您的子组件; isPrime
接受 int ;你不希望在任何 int 上调用它,但如果你做了什么呢?而不是测试每个可能的 int ,divide the domain into equivalence classes and check the boundaries:如果它可以得到的那么小,该怎么办?如果它能够获得的大小怎么办?如果它为零怎么办?如果它刚刚超过零怎么办?如果它低于零怎么办?已知的素数,非素数和各种大小的伪素数。 (顺便说一下,isPrime (~1)
也会导致溢出。)
制作isPrime
robust:
fun isPrime num =
num > 1 andalso detPrime (num, 2)