Pelles C forum

C language => Beginner questions => Topic started by: Grincheux on November 14, 2020, 12:29:58 PM

Title: atof
Post by: Grincheux on November 14, 2020, 12:29:58 PM
The function atof rouds my results!


I have strings with 15 numbers after the decimal point and I can't get correct double or float numer.
Is there a solution (without writing my own).
Title: Re: atof
Post by: Grincheux on November 14, 2020, 01:10:40 PM
I had a best result using strtold


Code: [Select]
*(_lpszDatas + 17) = '\0' ;
// _dJulianDate = atof(_lpszDatas) ;
_dJulianDate = (double) strtold(_lpszDatas,NULL) ;
Title: Re: atof
Post by: Grincheux on November 14, 2020, 01:15:30 PM
I suppose that Pelle make the same thing:

Code: [Select]
/* Copyright (C) 1991-2019 Free Software Foundation, Inc.
   This file is part of the GNU C Library.
   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.
   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.
   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, see
   <http://www.gnu.org/licenses/>.  */
#include <stdlib.h>
#undef        atof
/* Convert a string to a double.  */
double
atof (const char *nptr)
{
  return strtod (nptr, (char **) NULL);
}
Title: Re: atof
Post by: John Z on November 15, 2020, 12:16:09 PM
Hi Grincheux,

Not that I'm qualified to speak to this but I am aware that there was a bug report on using more than 11 or 12 digits after the decimal.  I think the suggestion was to use the advance math lib for now.


John Z
Title: Re: atof
Post by: Pelle on November 15, 2020, 08:48:02 PM
Maybe there is a problem somewhere, I havn't really hunted for anything yet, but there could also be the common case of having to high expectations about the binary floating-point format in general. There are only so many decimals you can expect to be correct.

If you have trouble sleeping, this may (or may not) help:
"What Every Computer Scientist Should Know About Floating-Point Arithmetic"
https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html (https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html)

Also, like Microsoft, there is no (at least shouldn't be any) difference between double and long double type.
Title: Re: atof
Post by: MrBcx on November 15, 2020, 11:53:40 PM

If you have trouble sleeping, this may (or may not) help:
"What Every Computer Scientist Should Know About Floating-Point Arithmetic"
https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html (https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html)
I found the following equations, under the PROOF section, to be particularly effective at helping me to fall asleep.

To get the general formula for Sk and Ck, expand the definitions of sk and ck, ignoring all terms involving xi with i > 1 to get

sk = (sk - 1 + yk)(1 + k)
= [sk - 1 + (xk - ck - 1) (1 + k)](1 + k)
= [(sk - 1 - ck - 1) - kck - 1](1+k)
ck = [{sk - sk - 1}(1 + k) - yk](1 + k)
= [{((sk - 1 - ck - 1) - kck - 1)(1 + k) - sk - 1}(1 + k) + ck - 1(1 + k)](1 + k)
= [{(sk - 1 - ck - 1)k - kck-1(1 + k) - ck - 1}(1 + k) + ck - 1(1 + k)](1 + k)
= [(sk - 1 - ck - 1)k(1 + k) - ck - 1(k + k(k + k + kk))](1 + k),
sk - ck = ((sk - 1 - ck - 1) - kck - 1) (1 + k)
- [(sk - 1 - ck - 1)k(1 + k) - ck - 1(k + k(k + k + kk)](1 + k)
= (sk- 1 - ck - 1)((1 + k) - k(1 + k)(1 + k))
+ ck - 1(-k(1 + k) + (k + k(k + k + kk)) (1 + k))
= (s- 1 - ck - 1) (1 - k(k + k + kk))
+ ck - 1 - [k + k + k(k + kk) + (k + k(k + k + kk))k]



Title: Re: atof
Post by: Grincheux on November 16, 2020, 02:34:35 PM
In fact I have trouble for sleeping, only two or three hours a night!
This formula will give me a headache that's all, nothing for sleeping.
I have looked at many post (stackoverflow...) many people have the problem.
I download ephemeris from the nasa (https://ssd.jpl.nasa.gov/horizons.cgi (https://ssd.jpl.nasa.gov/horizons.cgi)) their programs are written using FORTRAN.
I have solved the problem in an other way.
I thank every one for the help.

This could help someone : http://arrayfire.org/docs/index.htm (http://arrayfire.org/docs/index.htm) and https://gmplib.org/ (https://gmplib.org/)
It seems too hard for me.


Merci
Title: Re: atof
Post by: Pelle on November 16, 2020, 05:55:14 PM
In fact I have trouble for sleeping, only two or three hours a night!
This formula will give me a headache that's all, nothing for sleeping.
Me too, sometimes. My point was that this isn't "easy reading", if fact it requires a lot of time and thinking, but some of this information has proven useful to some people in the past, so I thought I share the link again.

Apart from that, if you still have problems, maybe a more complete example with the actual input to atof() (or whatever) may produce better help/answers.
Title: Re: atof
Post by: Grincheux on November 16, 2020, 06:24:36 PM
Yes but I don't where is the problem because when using strtold, atof, or sqlite3_snprintf.
It seems there is the problem in all the functions.

I have solved it in modifying the %f argument.

I need 15 numbers after the decimal point :
sqlite3_snprintf(sizeof(_szTmp),_szTmp,"%.15f",_dDistanceLaPlusProche)  ;
so I format with 16 numbers
sqlite3_snprintf(sizeof(_szTmp),_szTmp,"%.16f",_dDistanceLaPlusProche) ;

With the other functions I have not any solution.

I have not tried with snprintf (don't want MS functions).
I have not tried by replacing %f by %g

My avatar is what I am actually doing.

Thank You for your help
Your compiler is the BEST
Title: Re: atof
Post by: frankie on November 17, 2020, 10:02:42 AM
The point is that the number of significant digits that we can express with a double float is approximately 16 decimal (decimal intended as base 10 not as after decimal point) digits (53 bits => log10(2) ≈ 15.955), and really means all significant decimal digits before and after the decimal point.
So you can't expect to have 15 significant decimal for numbers bigger or equal to 1.
If you need such precision you should use a math library with extended precision.
Title: Re: atof
Post by: Grincheux on November 18, 2020, 11:33:52 AM
Thank You Frankie I expected an other solution, but with your post it is clear I must change something. Perhaps I could multiply by 100 so there will be only five numbers after the decimal point.


With the help every one gave me, I can say the post is closed.
Title: Re: atof
Post by: TimoVJL on November 18, 2020, 09:23:00 PM
I still waits what those numbers are.
Give us series of those numbers to check.
Title: Re: atof
Post by: Grincheux on November 21, 2020, 04:06:56 PM
Here are examples
Quote
2466285.687500000, A.D. 2040-May-11 04:30:00.0000,  1.556590248345051E+09,  2.709382709369094E+08, -8.836233844876927E+07, -7.653652678628662E+00,  3.833227168750318E+01, -4.593642982153394E-01,  5.278527865450719E+03,  1.582462843404964E+09, -9.398838110390882E-01,
2466285.708333333, A.D. 2040-May-11 05:00:00.0000,  1.556576462563047E+09,  2.710072669242373E+08, -8.836316353478888E+07, -7.663882752316741E+00,  3.832993585150521E+01, -4.573979376624084E-01,  5.278522195719391E+03,  1.582461143662273E+09, -9.487191675119203E-01,
2466285.729166667, A.D. 2040-May-11 05:30:00.0000,  1.556562658367611E+09,  2.710762587037903E+08, -8.836398508131553E+07, -7.674112045828995E+00,  3.832759637718574E+01, -4.554315282629915E-01,  5.278516472939437E+03,  1.582459428016004E+09, -9.575544522874865E-01,
2466285.750000000, A.D. 2040-May-11 06:00:00.0000,  1.556548835760150E+09,  2.711452462690158E+08, -8.836480308826166E+07, -7.684340557115283E+00,  3.832525326549152E+01, -4.534650705151737E-01,  5.278510697111295E+03,  1.582457696466289E+09, -9.663896636982247E-01,
2466285.770833333, A.D. 2040-May-11 06:30:00.0000,  1.556534994742076E+09,  2.712142296133627E+08, -8.836561755554067E+07, -7.694568284329571E+00,  3.832290651737497E+01, -4.514985649057817E-01,  5.278504868235410E+03,  1.582455949013259E+09, -9.752248002768448E-01,
2466285.791666667, A.D. 2040-May-11 07:00:00.0000,  1.556521135314799E+09,  2.712832087302955E+08, -8.836642848306687E+07, -7.704795225828729E+00,  3.832055613379973E+01, -4.495320119136608E-01,  5.278498986312236E+03,  1.582454185657053E+09, -9.840598607536791E-01,
2466285.812500000, A.D. 2040-May-11 07:30:00.0000,  1.556507257479735E+09,  2.713521836132668E+08, -8.836723587075542E+07, -7.715021380166704E+00,  3.831820211575668E+01, -4.475654120184007E-01,  5.278493051342231E+03,  1.582452406397807E+09, -9.928948440483559E-01,
2466285.833333333, A.D. 2040-May-11 08:00:00.0000,  1.556493361238303E+09,  2.714211542557307E+08, -8.836803971852225E+07, -7.725246746101247E+00,  3.831584446427977E+01, -4.455987657079348E-01,  5.278487063325862E+03,  1.582450611235662E+09, -1.001729749272952E+00,
2466285.854166667, A.D. 2040-May-11 08:30:00.0000,  1.556479446591923E+09,  2.714901206511572E+08, -8.836884002628440E+07, -7.735471322605457E+00,  3.831348318045865E+01, -4.436320734841406E-01,  5.278481022263600E+03,  1.582448800170757E+09, -1.010564575740471E+00,
2466285.875000000, A.D. 2040-May-11 09:00:00.0000,  1.556465513542015E+09,  2.715590827930046E+08, -8.836963679395960E+07, -7.745695108875569E+00,  3.831111826544660E+01, -4.416653358663005E-01,  5.278474928155919E+03,  1.582446973203236E+09, -1.019399322971638E+00,
2466285.895833333, A.D. 2040-May-11 09:30:00.0000,  1.556451562090006E+09,  2.716280406747333E+08, -8.837043002146657E+07, -7.755918104349613E+00,  3.830874972045784E+01, -4.396985533885100E-01,  5.278468781003298E+03,  1.582445130333242E+09, -1.028233990713471E+00,
2466285.916666667, A.D. 2040-May-11 10:00:00.0000,  1.556437592237315E+09,  2.716969942898195E+08, -8.837121970872520E+07, -7.766140308727367E+00,  3.830637754675538E+01, -4.377317265922063E-01,  5.278462580806210E+03,  1.582443271560917E+09, -1.037068578961048E+00,
2466285.937500000, A.D. 2040-May-11 10:30:00.0000,  1.556423603985368E+09,  2.717659436317282E+08, -8.837200585565612E+07, -7.776361721981864E+00,  3.830400174563097E+01, -4.357648560154441E-01,  5.278456327565135E+03,  1.582441396886405E+09, -1.045903087973520E+00,
2466285.958333333, A.D. 2040-May-11 11:00:00.0000,  1.556409597335591E+09,  2.718348886939266E+08, -8.837278846218090E+07, -7.786582344376431E+00,  3.830162231837438E+01, -4.337979421764349E-01,  5.278450021280551E+03,  1.582439506309848E+09, -1.054737518296720E+00,
Title: Re: atof
Post by: frankie on November 22, 2020, 01:22:06 PM
Thank You Frankie I expected an other solution, but with your post it is clear I must change something. Perhaps I could multiply by 100 so there will be only five numbers after the decimal point.
I don't think it will solve your problem.
Multiplying by 100 moves the decimal point, but don't change the total number of digit figures of the number, ergo the whole digits that make up your number still can't be enclosed in the 54 bits (53 real plus an implicit bit), and can't be represented without approximations.
When approximations comes in all the issues, explained in the paper reported by Pelle, start to play.
In very plain words: if you need high precision calculations without any tricky approximation, be sure that all your numbers, removing the decimal point, are less than 2^54-1.
In your case you can find convenient to work with quadruple precision float, standard "IEEE 754 2008 binary128", that use 128bits.
Many free libraries are available, among them you can try QPFloat (https://github.com/coder0xff/QPFloat) (C++) this in C (https://www.codeproject.com/Articles/1206126/Quadruple-precision-floating-point-calculations-in).
Title: Re: atof
Post by: Grincheux on November 23, 2020, 06:33:14 PM
I have read something about what you told.
I have read too that a programmer gave numbers in the form of a string.
What about transforming in two 64 bits numbers.
Than You Frankie for your help.
Title: Re: atof
Post by: MrBcx on November 23, 2020, 08:22:15 PM

I have read too that a programmer gave numbers in the form of a string.
 

I have ugly code that I wrote in 1992 that creates 3 functions -- fpAdd, fpSub, and fpMul.
Each takes 2 string arguments.  The BASIC code was written for MSDOS but compiles with Pelles
when converted using my BCX translator.

Examples:

PRINT fpAdd$ ("999.123456789","100")

PRINT fpSub$ ("500.987654321","100")

PRINT fpMul$ ("999999999999999999.123456789","999999999999999999.123456789")


OUTPUT

1099.123456789
400.987654321
999999999999999998246913578000000000.768328000750190521


Impressively, the fpMul result matches the result obtained here:

https://keisan.casio.com/calculator

Title: Re: atof
Post by: Grincheux on November 23, 2020, 08:28:50 PM
A good thing and impressive calculator!
I also have found LibBF and GNU MPFR but there is no Windows Version!
It is possible using MinGW but too complicated for me.
Title: Re: atof
Post by: TimoVJL on November 23, 2020, 08:40:20 PM
Check
https://forum.pellesc.de/index.php?topic=7184.msg27264#msg27264

EDIT:
https://www.davidhbailey.com/dhbsoftware/
Title: Re: atof
Post by: frankie on November 24, 2020, 12:10:27 AM
What about transforming in two 64 bits numbers.
Than You Frankie for your help.
I would avoid to to reinvent the wheel and write your own math library.
You can use the QD library ported by Timovjl.
I also found another quad precision float library that seems interesting: the HPALIB (https://www.nongnu.org/hpalib/) (High Precision Arithmetic library).
The IEEE 754 2008 binary128 uses 1 bit for sign, 15bits for exponent and 113bits for mantissa. 113bits means 33 significant digits. This means that you can work i.e. with numbers of 16 digits before decimal dot and 16 digits after without precision loss.
Title: Re: atof
Post by: Grincheux on November 24, 2020, 06:18:01 PM
There are too many numbers after the decimal point!


Thank You Frankie & Timo I will use the library
Title: Re: atof
Post by: TimoVJL on November 25, 2020, 05:11:02 PM
QDC library should follow lisence:
https://www.davidhbailey.com/dhbsoftware/LBNL-BSD-License.docx

PS.
David H Bailey accept that QDC project.