NO

Author Topic: atof  (Read 590 times)

Offline Grincheux

  • Member
  • *
  • Posts: 73
  • Never be pleased, always improve
    • Arachne
atof
« 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).
-------------------------
Kenavo / Bye

Offline Grincheux

  • Member
  • *
  • Posts: 73
  • Never be pleased, always improve
    • Arachne
Re: atof
« Reply #1 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) ;
-------------------------
Kenavo / Bye

Offline Grincheux

  • Member
  • *
  • Posts: 73
  • Never be pleased, always improve
    • Arachne
Re: atof
« Reply #2 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);
}
« Last Edit: November 14, 2020, 01:17:34 pm by Grincheux »
-------------------------
Kenavo / Bye

Offline John Z

  • Member
  • *
  • Posts: 109
Re: atof
« Reply #3 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

Offline Pelle

  • Administrator
  • Member
  • *****
  • Posts: 2084
    • http://www.smorgasbordet.com
Re: atof
« Reply #4 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

Also, like Microsoft, there is no (at least shouldn't be any) difference between double and long double type.
/Pelle

Offline MrBcx

  • Global Moderator
  • Member
  • *****
  • Posts: 67
    • http://www.bcxgurus.com/
Re: atof
« Reply #5 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
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]





Offline Grincheux

  • Member
  • *
  • Posts: 73
  • Never be pleased, always improve
    • Arachne
Re: atof
« Reply #6 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) 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 and https://gmplib.org/
It seems too hard for me.


Merci
« Last Edit: November 16, 2020, 02:53:23 pm by Grincheux »
-------------------------
Kenavo / Bye

Offline Pelle

  • Administrator
  • Member
  • *****
  • Posts: 2084
    • http://www.smorgasbordet.com
Re: atof
« Reply #7 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.
/Pelle

Offline Grincheux

  • Member
  • *
  • Posts: 73
  • Never be pleased, always improve
    • Arachne
Re: atof
« Reply #8 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
« Last Edit: November 16, 2020, 06:29:18 pm by Grincheux »
-------------------------
Kenavo / Bye

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 1775
Re: atof
« Reply #9 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.

Offline Grincheux

  • Member
  • *
  • Posts: 73
  • Never be pleased, always improve
    • Arachne
Re: atof
« Reply #10 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.
-------------------------
Kenavo / Bye

Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 1902
Re: atof
« Reply #11 on: November 18, 2020, 09:23:00 pm »
I still waits what those numbers are.
Give us series of those numbers to check.
May the source be with you

Offline Grincheux

  • Member
  • *
  • Posts: 73
  • Never be pleased, always improve
    • Arachne
Re: atof
« Reply #12 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,
-------------------------
Kenavo / Bye

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 1775
Re: atof
« Reply #13 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 (C++) this in C.
« Last Edit: November 22, 2020, 04:20:01 pm by frankie »

Offline Grincheux

  • Member
  • *
  • Posts: 73
  • Never be pleased, always improve
    • Arachne
Re: atof
« Reply #14 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.
-------------------------
Kenavo / Bye