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