Testing if a float has a zero fractional part
----------------------------------------
Tests for x = 1.0000000000009095E+000
Using SameValue: TRUE
Using frac : FALSE
Value of frac : 9.0949470177292824E-013
Tests for x = 9.9999999999999995E-021
Using SameValue: TRUE
Using frac : FALSE
Value of frac : 9.9999999999999995E-021
Huh? Nonsense. You forget that the least significant values can not be expressed in decimal
I got different result in the first case:Thank you for the feedback.
Using SameValue: FALSE
Lazarus 1.9.0 r57941M FPC 3.1.1 x86_64-linux-qt
All numbers are binary. So, there is no such things, as "machine epsilon" here.See https://en.wikipedia.org/wiki/Machine_epsilon, definition b.
Any float value (except 80-bit one - it's stored in "raw" form) is stored in following form:The <exponent> field is the biased exponent (https://en.wikipedia.org/wiki/Double-precision_floating-point_format), so shifting with this field will cause overflow in many cases.
<mantissa sign>(1).<mantissa>*2^(<exponent sign><exponent>)... If after shifting (1)<mantissa> left by <exponent sign><exponent> bits it's still non-zero - then this float value has fractional part.
Floating point value is exactly the same, as fixed point value. I.e. X bits go to integer part and Y=N-X, where N - is number of bits in mantissa, bits go fractional part. Only difference - point isn't fixed, i.e. we can set, how many bits go to integer part and how many to fractional one. Via exponent. And of course point can go out of bit field range - value is padded by zeros then. This just makes floating point values more flexible - number of bits, allocated for integer and fractional parts, depends on our task. And "floating point value has fractional part" = "fractional part has at least one bit and at least one bit in fractional part isn't zero". Shifting causes overflow? That's, what we actually need, because our goal is - to remove integer part.All numbers are binary. So, there is no such things, as "machine epsilon" here.See https://en.wikipedia.org/wiki/Machine_epsilon, definition b.Any float value (except 80-bit one - it's stored in "raw" form) is stored in following form:The <exponent> field is the biased exponent (https://en.wikipedia.org/wiki/Double-precision_floating-point_format), so shifting with this field will cause overflow in many cases.
<mantissa sign>(1).<mantissa>*2^(<exponent sign><exponent>)... If after shifting (1)<mantissa> left by <exponent sign><exponent> bits it's still non-zero - then this float value has fractional part.
Even if you shift with the unbiased exponent this is mostly wrong because all double precision numbers >= 2^52 have a zero fractional part (and I guess with fractional part you mean non-zero fractional part)
Floating point value is exactly the same, as fixed point value. I.e. X bits go to integer part and Y=N-X, where N - is number of bits in mantissa, bits go fractional part. Only difference - point isn't fixed, i.e. we can set, how many bits go to integer part and how many to fractional one.Incorrect. You confuse fractional part with significand (or mantissa). Frac(x) returns the non-integer part of x (see https://www.freepascal.org/docs-html/rtl/system/frac.html). Since there are only 52 explicit and one implied bits in the significand of a binary-64 double, all double precision numbers x > 2^52 have frac(x)=0, ie are integers (this feature is used in the new code for frac, https://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/rtl/x86_64/math.inc?r1=38856&r2=38903), all x > 2^53 are even integers etc.
D:\Work\DAMath>D:\FPC304\bin\i386-win32\ppcrossx64.exe xx2.pas
Free Pascal Compiler version 3.0.4 [2017/10/06] for x86_64
Copyright (c) 1993-2017 by Florian Klaempfl and others
Target OS: Win64 for x64
Compiling xx2.pas
Linking xx2.exe
12 lines compiled, 0.2 sec, 71680 bytes code, 4980 bytes data
D:\Work\DAMath>xx2.exe
5.432101234568E+015 0.000000000000E+000 5432101234567890.00000
5.432101234568E+015 0.000000000000E+000 5432101234567892.00000
5.432101234568E+015 0.000000000000E+000 5432101234567891.00000
9.432101234568E+015 0.000000000000E+000 9432101234567892.00000