为什么我会收到错误 207(无效的浮点运算)/如何解决?
Why am I'm getting an Error 207 (invalid floating point operation)/ How to get around it?
program cosseno;
var fat1, fat2, n1, n2, cont1, cont2, s :real;
begin
s := 0.5;
fat1 := 24;
fat2 := 720;
n1 := 1/fat1;
n2 := 1/fat2;
cont1 := 8;
cont2 := 10;
while (n1 - n2) > 0.000001 do
begin
fat1 := (cont1) * (cont1-1) * (cont1-2) * (cont1-3) * fat1;
fat2 := (cont2) * (cont2-1) * (cont2-2) * (cont2-3) * fat2;
cont1 := cont1 + 4;
cont2 := cont2 + 4;
n1 := n1 + 1/fat1;
n2 := n2 + 1/fat2;
end;
s := s + n1 - n2;
writeln(s);
end.
这是一个估算cos(1 rad)e值的程序,显然错误发生在while段。
问题
问题是您的变量 fat1 变得太大而溢出。使用 free pascal,您的代码会导致 205 错误(浮点数溢出)。这类似于 207 Invalid floating point operation - free pascal run-time error codes. The real types that are relevant to your code have the following constraints (from the free pascal data types wiki page):
Type Range Significant digits Bytes
Real platform dependent ??? 4 or 8
Single 1.5E-45 .. 3.4E38 7-8 4
Double 5.0E-324 .. 1.7E308 15-16 8
Extended 1.9E-4932 .. 1.1E4932 19-20 10
解决方法
您只需要考虑最大变量溢出的可能性。不可能简单地检查变量是否高于其最大值,因此您应该执行可能导致溢出的操作的相反操作。我还使用 Extended
进行了更好的估计。
var max_fat : Extended = 1.1 * power(10,4932);
var should_step : Extended= max_fat / (cont1) / (cont1-1) / (cont1-2) / (cont1-3);
然后在你的 while 循环中包括检查:
fat1 < should_step
这个逆运算的结果就是变量fat1
在溢出前所能达到的最大值。我使用 Math 库来帮助计算最大值 Extended
。以下测试代码适用于我:
program cosseno;
Uses Math;
var fat1, fat2, n1, n2, cont1, cont2, s, max_fat, should_step : Extended;
begin
s := 0.5;
fat1 := 24;
fat2 := 720;
n1 := 1/fat1;
n2 := 1/fat2;
cont1 := 8;
cont2 := 10;
max_fat := 1.1 * power(10,4932);
should_step := max_fat;
while ((n1 - n2) > 0.000001) AND (fat1 < should_step) do
begin
should_step := max_fat / (cont1) / (cont1-1) / (cont1-2) / (cont1-3);
fat1 := (cont1) * (cont1-1) * (cont1-2) * (cont1-3) * fat1;
fat2 := (cont2) * (cont2-1) * (cont2-2) * (cont2-3) * fat2;
cont1 := cont1 + 4;
cont2 := cont2 + 4;
n1 := n1 + 1/fat1;
n2 := n2 + 1/fat2;
writeln('fat1 > ', fat1);
writeln('fat2 > ', fat2);
writeln('cont1 > ', cont1);
writeln('cont2 > ', cont2);
writeln('n1 > ', n1);
writeln('n2 > ', n2);
end;
s := s + n1 - n2;
writeln('<==================>');
writeln(s);
end.
代码产生以下结果:
5.40302305868139717414E-0001
我检查至少前 10 个数字是正确的。
program cosseno;
var fat1, fat2, n1, n2, cont1, cont2, s :real;
begin
s := 0.5;
fat1 := 24;
fat2 := 720;
n1 := 1/fat1;
n2 := 1/fat2;
cont1 := 8;
cont2 := 10;
while (n1 - n2) > 0.000001 do
begin
fat1 := (cont1) * (cont1-1) * (cont1-2) * (cont1-3) * fat1;
fat2 := (cont2) * (cont2-1) * (cont2-2) * (cont2-3) * fat2;
cont1 := cont1 + 4;
cont2 := cont2 + 4;
n1 := n1 + 1/fat1;
n2 := n2 + 1/fat2;
end;
s := s + n1 - n2;
writeln(s);
end.
这是一个估算cos(1 rad)e值的程序,显然错误发生在while段。
问题
问题是您的变量 fat1 变得太大而溢出。使用 free pascal,您的代码会导致 205 错误(浮点数溢出)。这类似于 207 Invalid floating point operation - free pascal run-time error codes. The real types that are relevant to your code have the following constraints (from the free pascal data types wiki page):
Type Range Significant digits Bytes
Real platform dependent ??? 4 or 8
Single 1.5E-45 .. 3.4E38 7-8 4
Double 5.0E-324 .. 1.7E308 15-16 8
Extended 1.9E-4932 .. 1.1E4932 19-20 10
解决方法
您只需要考虑最大变量溢出的可能性。不可能简单地检查变量是否高于其最大值,因此您应该执行可能导致溢出的操作的相反操作。我还使用 Extended
进行了更好的估计。
var max_fat : Extended = 1.1 * power(10,4932);
var should_step : Extended= max_fat / (cont1) / (cont1-1) / (cont1-2) / (cont1-3);
然后在你的 while 循环中包括检查:
fat1 < should_step
这个逆运算的结果就是变量fat1
在溢出前所能达到的最大值。我使用 Math 库来帮助计算最大值 Extended
。以下测试代码适用于我:
program cosseno;
Uses Math;
var fat1, fat2, n1, n2, cont1, cont2, s, max_fat, should_step : Extended;
begin
s := 0.5;
fat1 := 24;
fat2 := 720;
n1 := 1/fat1;
n2 := 1/fat2;
cont1 := 8;
cont2 := 10;
max_fat := 1.1 * power(10,4932);
should_step := max_fat;
while ((n1 - n2) > 0.000001) AND (fat1 < should_step) do
begin
should_step := max_fat / (cont1) / (cont1-1) / (cont1-2) / (cont1-3);
fat1 := (cont1) * (cont1-1) * (cont1-2) * (cont1-3) * fat1;
fat2 := (cont2) * (cont2-1) * (cont2-2) * (cont2-3) * fat2;
cont1 := cont1 + 4;
cont2 := cont2 + 4;
n1 := n1 + 1/fat1;
n2 := n2 + 1/fat2;
writeln('fat1 > ', fat1);
writeln('fat2 > ', fat2);
writeln('cont1 > ', cont1);
writeln('cont2 > ', cont2);
writeln('n1 > ', n1);
writeln('n2 > ', n2);
end;
s := s + n1 - n2;
writeln('<==================>');
writeln(s);
end.
代码产生以下结果:
5.40302305868139717414E-0001
我检查至少前 10 个数字是正确的。