[Gcl-devel] Bug in mpz_get_d
Camm Maguire
camm at maguirefamily.org
Tue Dec 15 03:06:40 CET 2009
Greetings, and thanks for your reply!
Enrique Perez-Terron <enrio at online.no> writes:
> On Fri, 2009-12-11 at 15:12 -0500, Camm Maguire wrote:
>> Greetings! Workaround?
>>
>> >(setq a (numerator **))
>>
>> 10715086071862673209484250490600018105614048117055336074437503883703510511249361224931983788156958581275946729175531468251871452856923140435984577574698574803934567774824230985421074605062371141877954182153046474983581941267398767559165543946077062914571196477686542167660429831652624386837205668069375
>>
>> >(float a)
>>
>> 1.0715086071862672E301
>>
>> >(float (1+ a))
>>
>> 1.0715086071862673E301
>>
>> >(float (1- a))
>>
>> 1.0715086071862672E301
^
This is the problem. Even rounding toward 0 at
all times this should be ....673 from the digit
string above. This is presuming that rounding
toward zero in any base should not produce a number
lower by more than one least significant digit in
any other base. (true?)
>
> Testing GMP and MPFR directly
> $ ./test-gmp
> Using GMP and mpf_get_d:
> ================
> num = 10715086071862673209484250490600018105614048117055336074437503883703510511249361224931983788156958581275946729175531468251871452856923140435984577574698574803934567774824230985421074605062371141877954182153046474983581941267398767559165543946077062914571196477686542167660429831652624386837205668069375
> 1.071508607186267202E+301
>
> 1 + num = 10715086071862673209484250490600018105614048117055336074437503883703510511249361224931983788156958581275946729175531468251871452856923140435984577574698574803934567774824230985421074605062371141877954182153046474983581941267398767559165543946077062914571196477686542167660429831652624386837205668069376
> 1.0715086071862673209E+301
>
> 1 - num = -10715086071862673209484250490600018105614048117055336074437503883703510511249361224931983788156958581275946729175531468251871452856923140435984577574698574803934567774824230985421074605062371141877954182153046474983581941267398767559165543946077062914571196477686542167660429831652624386837205668069374
> -1.071508607186267202E+301
>
(in lisp (1- a) = a - 1, so the sign issue is correct here).
>
> Using MPFR:
> ==================
>
> Num = 1.0715086071862673209E+301
>
> 1 + num = 1.0715086071862673209E+301
>
> 1 - num = -1.0715086071862673209E+301
>
> I don't know why float(1-a) turned positive.
>
> It is easy to miss that there is one correct and two wrong digit
> strings, not the other way around.
> Numbers ending in 7202 are the wrong ones, correct ending is 73209.
>
This was my thought -- do you agree that the mpz_get_d algorithm should
produce at least 73?
I have a temporary ugly workaround which calls mpz_get_str, and sscanf
for big integers, which is working for now, but clearly less than
optimal.
> Gcl already links with mpfr, no?
>
Alas, no. We just use mpz. For now at least.
Many thanks for the below!!!
Take care,
> Below is the C code. Compile with -lmpfr -lgmp.
> -Enrique
> ------------------------8<-----------------------------
> #include <stdio.h>
> #include <gmp.h>
> #include <mpfr.h>
>
> char *mynum = "10715086071862673209484250490600018105614048117055336074437503883703510511249361224931983788156958581275946729175531468251871452856923140435984577574698574803934567774824230985421074605062371141877954182153046474983581941267398767559165543946077062914571196477686542167660429831652624386837205668069375";
>
> main ()
> {
> printf("Using GMP and mpf_get_d:\n================\n");
> mpz_t num;
> mpz_init_set_str(num, mynum, 10);
> printf("num = ");
> mpz_out_str(stdout, 10, num);
> putchar('\n');
>
> mpf_t myfloat;
> mpf_init(myfloat);
> mpf_set_z(myfloat, num);
> printf("%-29.20lG\n\n", mpf_get_d(myfloat));
>
> mpz_t other;
> mpz_init_set_str(other, "1", 10);
> mpz_add(other, other, num);
> printf("1 + num = ");
> mpz_out_str(stdout, 10, other);
> putchar('\n');
>
> mpf_set_z(myfloat, other);
> printf("%-29.20lG\n\n", mpf_get_d(myfloat));
>
> mpz_set_ui(other, 1);
> mpz_sub(other, other, num);
> printf("1 - num = ");
> mpz_out_str(stdout, 10, other);
> putchar('\n');
>
> mpf_set_z(myfloat, other);
> printf("%-29.20lG\n", mpf_get_d(myfloat));
>
> printf("\n\nUsing MPFR:\n==================\n\n");
> mpfr_t mpfr;
> mpfr_init(mpfr);
> printf("Num = ");
> mpfr_set_z(mpfr, num, GMP_RNDN);
> printf("%-29.20lG\n\n", mpfr_get_d(mpfr, GMP_RNDN));
>
> mpz_set_ui(other, 1);
> mpz_add(other, other, num);
> printf("1 + num = ");
>
> mpfr_set_z(mpfr, other, GMP_RNDN);
> printf("%-29.20lG\n\n", mpfr_get_d(mpfr, GMP_RNDN));
>
> mpz_set_ui(other, 1);
> mpz_sub(other, other, num);
> printf("1 - num = ");
> mpfr_set_z(mpfr, other, GMP_RNDN);
> printf("%-29.20lG\n", mpfr_get_d(mpfr, GMP_RNDN));
>
> }
>
>
>
>
>
>
--
Camm Maguire camm at maguirefamily.org
==========================================================================
"The earth is but one country, and mankind its citizens." -- Baha'u'llah
More information about the gmp-bugs
mailing list