Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2026-05

function IsInt64(Double): Boolean;

5 messages · 3 people ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Ondrej Pokorny

Hello,

I am having a hard time to write a simple function that determines if a Double value is Int64:

function IsInt64(const aNumber: Double): Boolean;

I know about precision problems. I basically want to know if Round(aNumber) overflows.

In Delphi, Round() doesn't throw an exception if the value exceeds Int64 range, so it is safe to compare SameValue(aNumber, Round(aNumber)):

function OXmlIsInt64(const aNumber: Double): Boolean;
begin
     Result := not IsNan(aNumber) and not IsInfinite(aNumber) and
SameValue(Frac(aNumber), 0) and SameValue(aNumber, Round(aNumber));
end;

That's OK for me.

But in FPC, I get:
Project TestProject raised exception class 'External: FLT INVALID OPERATION' in Round().

Is there a chance to not throw this exception? I expect this problem so I don't want to do something like:

function OXmlIsInt64(const aNumber: Double): Boolean;
begin
   try
     Result := not IsNan(aNumber) and not IsInfinite(aNumber) and
SameValue(Frac(aNumber), 0) and SameValue(aNumber, Round(aNumber));
   except
     Result := False;
   end;
end;
I tried to switch overflow checks off:
{$OVERFLOWCHECKS OFF}

But obviously it doesn't help (it's a different exception).

----

I'd really like to get rid of the try-except block... It's the same with StrToInt() vs TryStrToInt(). IMO there should be a possibility to catch expected errors without exceptions.

Any ideas?

Thanks
Ondrej

Reply by email

Martin Frb
to Ondrej Pokorny
Ondrej Pokorny wrote 5 lines
I tried to switch overflow checks off: {$OVERFLOWCHECKS OFF} But obviously it doesn't help (it's a different exception).

AFAIK:
You need to use SetExceptionMask, I think the below example should do:

procedure DisableFloatExceptions;
begin
   if FloatExceptionLock = 0 then begin
     EM := GetExceptionMask;
     SetExceptionMask(EM + [exInvalidOp, exDenormalized, exZeroDivide,
exOverflow, exUnderflow, exPrecision]);
   end;
   inc(FloatExceptionLock);
end;
procedure EnableFloatExceptions;
begin
   dec(FloatExceptionLock);
   if FloatExceptionLock <= 0 then begin
     FloatExceptionLock := 0;
     ClearExceptions(False);
     SetExceptionMask(EM);
   end;
end;

Reply by email

J. Gareth Moreton
to Martin Frb

The quickest way, I think, is to look at the exponent bits of the Double.  Though it returns a false negative for -(2^63):

function OXmlIsInt64(const aNumber: Double): Boolean;
var
   ExpMask: LongWord;
   DoubleBits: LongWord absolute aNumber;
begin
   ExpMask := (DoubleBits shr 52) and $7FF;
   Result := (ExpMask >= $3FF) and (ExpMask < $43F);
end;

I think that's correct - I haven't actually tested it though. Note it only works for the standard IEEE 754 Double.

Kit

Martin Frb wrote 37 lines
On 04/05/2026 22:34, Ondrej Pokorny via fpc-devel wrote: > > I tried to switch overflow checks off: > {$OVERFLOWCHECKS OFF} > > But obviously it doesn't help (it's a different exception). AFAIK: You need to use SetExceptionMask, I think the below example should do: procedure DisableFloatExceptions; begin   if FloatExceptionLock = 0 then begin     EM := GetExceptionMask;     SetExceptionMask(EM + [exInvalidOp, exDenormalized, exZeroDivide, exOverflow, exUnderflow, exPrecision]);   end;   inc(FloatExceptionLock); end; procedure EnableFloatExceptions; begin   dec(FloatExceptionLock);   if FloatExceptionLock <= 0 then begin     FloatExceptionLock := 0;     ClearExceptions(False);     SetExceptionMask(EM);   end; end; _______________________________________________ fpc-devel maillist  -  https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
This email has been checked for viruses by Avast antivirus software. www.avast.com

Reply by email

J. Gareth Moreton
to J. Gareth Moreton

Oh, minor error, the $43F constant is meant to be $43E.

Kit

J. Gareth Moreton wrote 56 lines
The quickest way, I think, is to look at the exponent bits of the Double.  Though it returns a false negative for -(2^63): function OXmlIsInt64(const aNumber: Double): Boolean; var   ExpMask: LongWord;   DoubleBits: LongWord absolute aNumber; begin   ExpMask := (DoubleBits shr 52) and $7FF;   Result := (ExpMask >= $3FF) and (ExpMask < $43F); end; I think that's correct - I haven't actually tested it though. Note it only works for the standard IEEE 754 Double. Kit On 04/05/2026 21:48, Martin Frb via fpc-devel wrote: > On 04/05/2026 22:34, Ondrej Pokorny via fpc-devel wrote: >> >> I tried to switch overflow checks off: >> {$OVERFLOWCHECKS OFF} >> >> But obviously it doesn't help (it's a different exception). > > AFAIK: > You need to use SetExceptionMask, I think the below example should do: > > > procedure DisableFloatExceptions; > begin >   if FloatExceptionLock = 0 then begin >     EM := GetExceptionMask; >     SetExceptionMask(EM + [exInvalidOp, exDenormalized, exZeroDivide, > exOverflow, exUnderflow, exPrecision]); >   end; >   inc(FloatExceptionLock); > end; > > procedure EnableFloatExceptions; > begin >   dec(FloatExceptionLock); >   if FloatExceptionLock <= 0 then begin >     FloatExceptionLock := 0; >     ClearExceptions(False); >     SetExceptionMask(EM); >   end; > > end; > > > _______________________________________________ > fpc-devel maillist  -  > https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel >
This email has been checked for viruses by Avast antivirus software. www.avast.com

Reply by email

Ondrej Pokorny
to Martin Frb: AFAIK: You need to use SetExceptionMask, I think the below example should do: procedure…
Martin Frb wrote 9 lines
On 04/05/2026 22:34, Ondrej Pokorny via fpc-devel wrote: > > I tried to switch overflow checks off: > {$OVERFLOWCHECKS OFF} > > But obviously it doesn't help (it's a different exception). AFAIK: You need to use SetExceptionMask, I think the below example should do:

Yes, that's it. And this is also the difference to Delphi. Thank you very much!

Ondrej

Reply by email