in reply to Re^7: subtraction issue
in thread subtraction issue

I can actually find one a lot longer, using the structure. Start with ou = 1 + ULP => 1 + 2**-52 -- that's the farthest separation between two active bits possible in a double. Then, shift it as far to the right of the decimal point as you can: x = ou * 2**-1022 = 2**-1022 + 2**-1074. The MPFR shows 303 digits. But I don't think that's all the digits. I actually expect 2**-1022 to take 1022 digits (including leading zeros, not including the "0.") after a fixed decimal point. And 2**-1074 should take 1074 digits (including leading zeros) after a fixed decimal point, so the sum of those two should really go to the 10**-1074th place. Since it starts at the 308th digit after the fixed decmial point, I actually expect 765 digits.

use warnings; use strict; use Data::IEEE754::Tools 0.016 qw/:all/; use Math::MPFR qw/:mpfr/; use POSIX qw/floor ceil log10 log2/; Rmpfr_set_default_prec(1000); # easy to come up with one that takes many digits to express: my $x = nextUp( POS_NORM_SMALLEST() ); print "POS_NORM_SMALLEST = 2**-1022\n"; print "POS_NORM_SMALLEST+1ULP = (1 + 2**-52)*(2**-1022)\n"; print "\n"; print "( 1 ) \n"; print "(1 + -----)*(2**-1022)\n"; print "( 2**52) \n"; print "\n"; printf "IEEE754 Hex String: '%s'\n", hexstr754_from_double($x); printf "%-30a %-30s %-30s\n", $x, to_hex_floatingpoint($x), to_dec_flo +atingpoint($x); my $s=Math::MPFR->new($x); printf "[%d digits long]: %s\n", length($s)-6, $s; my $d = ceil(-log10($x)); # start digit printf "For _FIXED POINT_ notation,\n"; printf "\tstarts %d digits after the decimal point\n", $d; my $ulp = ulp($x); # value of last bit (whether or not it is +set) printf "long version of ulp: %s\n", Math::MPFR->new($ulp); my $l2 = log2($ulp); printf "log2(ulp) = %d, so I expect it to fit within %d digits of the +fixed decimal point\n", $l2, -$l2;
__OUTPUT__ POS_NORM_SMALLEST = 2**-1022 POS_NORM_SMALLEST+1ULP = (1 + 2**-52)*(2**-1022) ( 1 ) (1 + -----)*(2**-1022) ( 2**52) IEEE754 Hex String: '0010000000000001' 0x1.0000000000001p-1022 +0x1.0000000000001p-1022 +0d1.000 +0000000000002p-1022 [303 digits long]: 2.2250738585072018771558785585789482407880088486837 +041956131300312119688603996006965297904292212628858639037013670281908 +017171296072711910355127227413175152199055740043138804567803233377539 +881639177387328959246074229270113078053813397081653361296447449529789 +5212189790907838525833659018517896187998851504e-308 For _FIXED POINT_ notation, starts 308 digits after the decimal point

Since I don't know MPFR, I tried to look at it using Math::BigFloat, but I couldn't get it to stop prematurely rounding at about 30 digits after the fixed point, even with accuracy(1000) and precision(-1000). Apparently, I don't know BigFloat very well, either. I'm pretty busy the rest of the weekend, but I know what my coffee breaks at work next week are going to include: writing my own simplistic string-based fixed-point bigs, that can simply add two bigs, or divide a big by two, without all the overhead of modules I don't understand that seem to be rounding prematurely.

Replies are listed 'Best First'.
Re^9: subtraction issue
by syphilis (Archbishop) on Jan 28, 2017 at 22:34 UTC
    # easy to come up with one that takes many digits to express

    I eventually realized that if I increased the precision to 4000 bits (which is overkill) I would uncover values that require more digits:
    3 / (3566377 ** 47) 0x1.7f1efda69bf79p-1022 3.32997129135359853606999222704654320128433273140834060375717919336765 +633480476074271117603537227797195965402328724231998706388357189066271 +703262139769146889312212556637321188791634569121935603887648273923627 +861919579821592345988060019740748868666186270141425088422184655360375 +823488548150443554012541921413793579099043424106801075148744029407167 +466158885097383679527382985052678222745861830039508807658877054796192 +051679570983765540503801105423327949689320479645855971334458658126010 +779989548774133737798898372623216628041645234343358029716664630265490 +827644527215647502548686221202499548660963335999734105043799288928491 +124484505682527752151459948594916997840488088218758704043473479179413 +158767647452761573740845092915600087271621454476644430542364716529846 +19140625e-308
    This(excluding "." and "e-308") is 767 digits.

    Cheers,
    Rob
      Eventually, I googled this.

      Looks lie it addresses what we've been fiddling with.

      Cheers,
      Rob

        yes, that's exactly where I was trying, rather ineffectually, to get to. Thank for finding that.