Problems with mpfr_set_str() and decimal numbers

Dennis Clarke dclarke at blastwave.org
Tue Apr 16 07:13:17 UTC 2019


Trying to read in a decimal number on the command line and getting a
strange response.  Just ever so slightly wrong result.

Some other code I have was acting strange so I did this bit :

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#include <math.h>
#include <gmp.h>
#include <mpfr.h>

#define PREC 113 /* lowest reasonable precision */

int main (int argc, char *argv[])
{
     uint64_t bit_prec = PREC;
     mpfr_t input_m;
     int inex; /* mpfr retval */

     inex = mpfr_init_set_si(input_m, (long)0, MPFR_RNDN);
     /* check if a test integer was on the command line */
     if (argc<2){
         fprintf(stderr,"FAIL : test number and optional bit precision?\n");
         fprintf(stderr,"     : %s <integer> <bit precision>\n", argv[0]);
         fprintf(stderr,"     : default bit precision is %i\n\n", PREC);
         return (EXIT_FAILURE);
     }

     /* check if a bit precision parameter was on the command line */
     if (argc>2){
         bit_prec = (int)strtol(argv[2], (char **)NULL, 10);
         if (bit_prec>1023){
             bit_prec = 1024;
             printf("\nWARNING : limit precision to 1024 bits.\n");
         }
     } else {
         bit_prec = PREC;
     }
     printf("\nWe shall use %i bits of precision.\n", bit_prec);
     mpfr_set_default_prec((mpfr_prec_t)bit_prec);

     if (argc>1){
         /* int mpfr_set_str(mpfr_t rop, const char *s, int base, 
mpfr_rnd_t rnd)
          *
          *   Set rop to the value of the string s in base base, rounded
          *   in the direction rnd. See the documentation of mpfr_strtofr
          *   for a detailed description of the valid string formats.
          *   Contrary to mpfr_strtofr, mpfr_set_str requires the whole
          *   string to represent a valid floating-point number.
          *
          *   The meaning of the return value differs from other MPFR
          *   functions: it is 0 if the entire string up to the final null
          *   character is a valid number in base base;
          *   otherwise it is -1, and rop may have changed (users interested
          *   in the ternary value should use mpfr_strtofr instead).    */
         inex = mpfr_set_str(input_m, argv[1], 10, MPFR_RNDN);
         if ( inex < 0 ) {
             printf("\nFAIL : some mysterious problem happened!\n");
             printf("     : we tried to interpret %s\n", argv[1]);
             printf("     : however we seemed to get ");
             mpfr_printf("%.Rf\n", input_m);
             return (EXIT_FAILURE);
         }

         if (mpfr_number_p(input_m)==0){
             printf("\nFAIL : provide a reasonable decimal number.\n");
             return (EXIT_FAILURE);
         }

     } else {
         printf("\nFAIL : provide a nice base ten number!\n");
         printf("     : %s <some number> <bit precision>\n", argv[0]);
         return (EXIT_FAILURE);
     }

     printf("You seem to have entered %s\n", argv[1]);
     printf("Where mpfr_set_str() seems to see ");
     mpfr_printf("%.Rf\n", input_m);

     return (EXIT_SUCCESS);
}


So seems to work up until the numbers are large :

nix$ ./mpfr_set_str 1844674407370999

We shall use 113 bits of precision.
You seem to have entered 1844674407370999
Where mpfr_set_str() seems to see 1844674407370999.000000
nix$

Fine.

However :

nix$ ./mpfr_set_str 18446744073709551601

We shall use 113 bits of precision.
You seem to have entered 18446744073709551601
Where mpfr_set_str() seems to see 18446744073709551616.000000
nix$

Not sure where those last two digits went wrong.

nix$ ./mpfr_set_str 1844674407370955160

We shall use 113 bits of precision.
You seem to have entered 1844674407370955160
Where mpfr_set_str() seems to see 1844674407370955264.000000
nix$

nix$
nix$ ./mpfr_set_str 999999999999999

We shall use 113 bits of precision.
You seem to have entered 999999999999999
Where mpfr_set_str() seems to see 999999999999999.000000
nix$
nix$ ./mpfr_set_str 9999999999999990

We shall use 113 bits of precision.
You seem to have entered 9999999999999990
Where mpfr_set_str() seems to see 9999999999999990.000000
nix$ ./mpfr_set_str 9999999999999991

We shall use 113 bits of precision.
You seem to have entered 9999999999999991
Where mpfr_set_str() seems to see 9999999999999992.000000
nix$

Weird.

What am I missing ?


-- 
Dennis Clarke
RISC-V/SPARC/PPC/ARM/CISC
UNIX and Linux spoken
GreyBeard and suspenders optional


More information about the gmp-bugs mailing list