- Код: Выделить всё
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:8
program 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
Сейчас этот форум просматривают: Yandex [Bot] и гости: 6