Given an arbitrary floating point value (eg. 1.9041105342991877e+258 or -8.2727285363069939e-293) how can I determine the smallest representable value that can be added or subtracted from that FP value and cause it to actually change?
To demonstrate the problem:
$fp1 = 1.9041105342991877e+258;; $change = $fp1 - 1.9041105342991876e+258; ## note cha +nge from 7 to 6 in the last digit of the number being subtracted printf "% 25.17g\n% 25.17g\n", $fp1, $change;; 1.9041105342991886e+258 0 ## no chang +e $change = $fp1 - 1.9041105342991875e+258; printf "% 25.17g\n% 25.17g\n", $fp1, $change;; ## note cha +nge from 7 to 5 in last digit 1.9041105342991886e+258 0 ## no chang +e $change = $fp1 - 1.9041105342991874e+258; ## note cha +nge from 7 to 4 in last digit printf "% 25.17g\n% 25.17g\n", $fp1, $change;; 1.9041105342991886e+258 2.1337646185215534e+242 ## A change +! ### 1 ### ## Now try the increment instead of decrement $change = $fp1 - 1.9041105342991878e+258; ## note cha +nge from 7 to 8 in last digit printf "% 25.17g\n% 25.17g\n", $fp1, $change;; 1.9041105342991886e+258 -2.1337646185215534e+242 ## A change + straight away! ### 2 ### ##### Note that whilst the sign of the change at ### 1 ### & ### 2 ### + is different, the absolute value is the same.
So a restatement of the problem might be: Given 1.9041105342991877e+258 find the smallest number that can be both added to and subtracted from that number and will cause it to change value. Ie. 2.1337646185215534e+242
Now I try to work with the second value in the (eg.) above: -8.2727285363069939e-293
$fp2 = -8.2727285363069939e-293;; printf "% 25.17g\n", $fp2;; -7.9999999999999948e-293 ### WTF? ###
Please note: that number (-8.2727285363069939e-293) was output from a perl program. Though it is hard to reproduce, as there were random numbers involved.
My only explanation for why it comes out differently to what was entered is that -8.2727285363069939e-293 must be a "denormal number which can be produced as a result of calculations, and will be displayed, but when you initialise a variable with that value, it will normalise it; hence what comes out is different to what goes in.
All of which makes the problem I'm looking for a solution to -- that of finding the minimal representable change -- more complicated.
At this point someone is going to point me at this. Please don't, I've read it.
And someone is going to ask what is this for, which I could answer, but it would take us way off topic and doesn't change the posed problem.
For: | Use: | ||
& | & | ||
< | < | ||
> | > | ||
[ | [ | ||
] | ] |