为什么我收到错误207(浮点运算无效)/如何绕过它?

时间:2015-04-07 00:04:14

标签: floating-point runtime-error pascal fpc

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部分。

1 个答案:

答案 0 :(得分:0)

问题

问题是你的变量fat1变得太大而且溢出。使用free pascal,您的代码会导致205错误(浮点溢出)。这类似于207无效浮点运算 - free pascal run-time error codes。与您的代码相关的实际类型具有以下约束(来自free pascal data types wiki页面):

// A bit "safer" document ready, won't collide with other libraries that use $
jQuery(function($) {
    // Select all items with ID starting with "suit_"
    $('[id^="suit_"]').contextPopup({
        items : [{
            label : 'Set',
            action : function () {
                window.location.href = "?settest=" + $(this).attr('id');
            }
        },
        null, 
        {
            label : 'Throw',
            action : function () {
                window.location.href = "?throwtest=" + $(this).attr('id');
            }
        },
        ]
    });
});

解决方法

您只需考虑最大变量溢出的可能性。不可能简单地检查变量是否高于它的最大值,因此您应该执行可能导致溢出的操作的反向操作。我还使用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

然后在你的while循环中包括检查:

var max_fat : Extended = 1.1 * power(10,4932);
var should_step : Extended= max_fat / (cont1) / (cont1-1) / (cont1-2) / (cont1-3);

此反向操作的结果是变量fat1 < should_step 在溢出之前可以达到的最大值。我使用数学库来帮助计算最大fat1。以下测试代码适用于我:

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.

我检查了至少前10位是正确的。