为什么我会收到错误 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 个数字是正确的。