- Код: Выделить всё
- program Project1;
 uses Math;
 var
 R: Double =0;
 begin
 if R=NaN then;
 ReadLn;
 end.
Это так и должно быть или это баг?
Lazarus 3.8 (rev lazarus_3_8) FPC 3.2.2 x86_64-win64-win32/win64
Модератор: Модераторы
program Project1;
uses Math;
var
  R: Double =0;
begin
  if R=NaN then;
  ReadLn;
end.  Reading symbols from ./Project1...
(gdb) r
Starting program: /tmp/Project1 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Program received signal SIGFPE, Arithmetic exception.
0x00005555555800ab in $main () at Project1.pas:8
8         if R=NaN then;
(gdb) bt
#0  0x00005555555800ab in $main () at Project1.pas:8program Project1;
uses Math;
begin
if (0/0)=NaN then WriteLn('*');
end.
Спасибо, то что надо.Alexander писал(а):функция https://lazarus-ccr.sourceforge.io/docs ... isnan.html есть.
Просто мой вычислительный код спокойно работал в LCL приложении, а когда я его в консоли стал использовать, все эти проверки посыпались. Не хорошо это.Alexander писал(а):Это не простой вопрос, ведь формально тогда сравниваются нечисло и число.
Osmiy писал(а):Это так и должно быть или это баг?
  if d.IsNaN then
    ...
  SetExceptionMask(GetExceptionMask + [exInvalidOp]);
  if d = NaN then
    ...    
 
 program Project1;
uses Math;
var
  R: Double =0;
begin
  if IsNan( R ) then  WriteLn('*');
  ReadLn;
end. Alex2013 писал(а):Мдя "тихие нечисла" вещь в себе . (Честно говоря никогда не думал, что есть возможность добраться до них из кода на паскале )
Зы
В чем смысл сравнения ? Это же состояние FPU по идее его вообще нельзя записать в переменную.
То есть после какой-то операции оно может вылезти "как фаг" но пустая примерная которая просто лежит в памяти ни как содержать нечисло не может . Именно в этом смысл этого кода if (0/0)=NaN then WriteLn('*'); что-то сделано и это можно проверить но записать нечисло в переменную по идее нельзя (впрочем я опыта использования NaN не имею так что могу ошибаться )
Зы Зы
xchgeaxeax писал(а):Вы правы, что NaN это состояние сопроцессора. Но формат Extended (10-ти байтовое) для x87 вполне может хранить NaN. Тогда как Double или Single такого не могут.
 
 uses
  SysUtils, Math;
var
  d: Double;
  s: Single;
begin
  SetExceptionMask(GetExceptionMask + [exInvalidOp]);
  d := Double.NaN;
  s := Single.NaN;
  SetExceptionMask(GetExceptionMask - [exInvalidOp]);
  if d.IsNan then
    WriteLn('Ich bin Double NaN!');
  if s.IsNan then
    WriteLn('Ich bin Single NaN!');
end.

Sergei I. Gorelkin писал(а):Операции с NaN вызывают исключение,
{$mode objfpc}
uses
  SysUtils, Math;
var
  d: Double;
begin
  SetExceptionMask(GetExceptionMask - [exInvalidOp]);
  d := Power(Double.NaN, 0);
  WriteLn(d);
  d := Abs(Double.NaN) + 42;
  WriteLn(d); 
  ReadLn;
end.
 1.0000000000000000E+000
                     Nan 

Sergei I. Gorelkin писал(а):Power() - это не совсем вычисление степени в математическом смысле, в ней куча проверок граничных условий. В частности, при показателе степени 0 (а также -0) она ничего не вычисляет и возвращает единицу независимо от основания степени.
{$mode objfpc}
uses
  SysUtils, Math;
var
  d, sn: Double;
begin
  SetExceptionMask(GetExceptionMask - [exInvalidOp]);
  QWord(sn) := (QWord($7ff) shl 52) + 42;//сигнальный NaN
  try
    d := Power(sn, 0);
    WriteLn('Expected error, but got ', d.ToString);
  except
    WriteLn('Seems Ok');
  end;
  try
    d := Power(1, Double.NaN);
    WriteLn('Expected 1, got ', d.ToString);
  except
    WriteLn('Expected 1, but got error');
  end;
  try
    d := Power(2, Double.NaN);
    WriteLn('Expected NaN, got ', d.ToString);
  except
    WriteLn('Expected NaN, but got error');
  end;
  ReadLn;
end.
Expected error, but got 1
Expected 1, but got error
Expected NaN, but got error
{$mode objfpc}
uses
  SysUtils, Math;
var
  d: Double;
begin
  SetExceptionMask(GetExceptionMask - [exInvalidOp]);
  try
    d := Abs(Double.NaN);
    WriteLn('Abs(): ', d.ToString);
  except
    WriteLn('Abs() unexpected error');
  end;
  try
    d := Sqr(Double.NaN);
    WriteLn('Sqr(): ', d.ToString);
  except
    WriteLn('Sqr() unexpected error');
  end;
  try
    d := Sqrt(Double.NaN);
    WriteLn('Sqrt(): ', d.ToString);
  except
    WriteLn('Sqrt() unexpected error');
  end;
  try
    d := ArcTan(Double.NaN);
    WriteLn('ArcTan(): ', d.ToString);
  except
    WriteLn('ArcTan() unexpected error');
  end;
  try
    d := Ln(Double.NaN);
    WriteLn('Ln(): ', d.ToString);
  except
    WriteLn('Ln() unexpected error');
  end;
  try
    d := Sin(Double.NaN);
    WriteLn('Sin(): ', d.ToString);
  except
    WriteLn('Sin() unexpected error');
  end;
  try
    d := Cos(Double.NaN);
    WriteLn('Cos(): ', d.ToString);
  except
    WriteLn('Cos() unexpected error');
  end;
  try
    d := Exp(Double.NaN);
    WriteLn('Exp(): ', d.ToString);
  except
    WriteLn('Exp() unexpected error');
  end;
  try
    d := Round(Double.NaN);
    WriteLn('Round(): ', d.ToString);
  except
    WriteLn('Round() unexpected error');
  end;
  try
    d := Frac(Double.NaN);
    WriteLn('Frac(): ', d.ToString);
  except
    WriteLn('Frac() unexpected error');
  end;
  try
    d := Int(Double.NaN);
    WriteLn('Int(): ', d.ToString);
  except
    WriteLn('Int() unexpected error');
  end;
  try
    d := Trunc(Double.NaN);
    WriteLn('Trunc(): ', d.ToString);
  except
    WriteLn('Trunc() unexpected error');
  end;
  ReadLn;
end.
Abs(): Nan
Sqr(): Nan
Sqrt(): Nan
ArcTan(): Nan
Ln(): Nan
Sin() unexpected error
Cos() unexpected error
Exp(): Nan
Round() unexpected error
Frac(): Nan
Int(): Nan
Trunc() unexpected error
Вернуться в Free Pascal Compiler
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1