64 bit floating point library "fp64lib" precision issue

Can somebody help with basic use of library "fp64lib" on Arduino Uno ?
I am trying 64 bit floating point library to get more precision.
When i run the code below i still do get only 7 digits of precision.
1.111111111 + 1.111111111 = 2.222222328186035

19:28:03.999 -> 2.222222328186035

#include <fp64lib.h>

float64_t a = fp64_sd(1.111111111);

float64_t b = fp64_sd(1.111111111);

float64_t c ;

void setup() {

Serial.begin(9600);

float64_t c = fp64_add( a, b );

char *s = fp64_to_string( c, 17, 0 );

s = fp64_to_string( c, 17, 0 );

Serial.println( s );

}

void loop() {

}`


What do you suppose the default decimal precision of the above numeric literal might be, given that the gcc compiler for the Uno does not support type double?

Hint: try this code on the Uno:

void setup() {
Serial.begin(115200);
while(!Serial);
Serial.println(1.111111111,15);
Serial.println(2*1.111111111,15);
}

void loop() {}
1 Like

Thank you for the prompt reply.
The library documentation states 15 - 17 digits of accuracy.
https://fp64lib.org/
Using the recommended code i get:
22:36:22.340 -> 1.111111164093017

22:36:22.340 -> 2.222222328186035

While the float64 library might have 17 digits of accuracy, the numeric constant that you're passing to fp64_sd() is still a 32bit floating point number on AVR, and only has the 6-7 digits of accuracy.
GIGO. I don't know if fp64 has a method of starting with higher precision constants; it seems to me that that would be a pretty difficult thing to do

1 Like

Would appreciate if you kindly describe the use of this fp64lib.h Library with an example on UNO how the Library helps to get 3.141592653589793 (16-digit accuracy) instead of 3.141592 (7-digit accuracy) for PI. I read few documents, but could not progress much!

if you require 64bit real values I suggest you more to a microcontroller which supports 8byte doubles, e.g. Arduino Due, STM32, ESP32, etc

1 Like

If someone owns only 8-bit AVR and still requires 16-digit accuracy for float numbers, then it is worth of knowing the usage of the fp64lib.h Library.

ran this on a UNO

#include <fp64lib.h>

void setup() {
  Serial.begin(115200);
  double pid=3.141592653589793;
  Serial.println(pid*2.0, 17);
  float64_t pi = fp64_atof("3.141592653589793"), two = fp64_atof("2.0");
  float64_t pi2 = fp64_mul(pi, two);
  char *s = fp64_to_string(pi2, 17, 0);
  Serial.println(s);
}

void loop() {
}

gives

6.28318548202514648
6.283185307179585

the first result (using double calculations) is accurate to approximatly 7 significant digits the rest of the digits are rubbish
the second result using float64_t is accurate to 16 significant digits
of course you need to start with data acurate to 17 significant digits - reminds me of engineers who input data with 3 significant digits, did double calculations and printed results with 17 digits most of which were rubbish

EDIT: on an ESP8266 which uses 8byte doubles the first calculation pid*2.0, 17 gives

6.28318530717958800
3 Likes

@borispavlov Do you understand what the others wrote ? If you don't understand it, then just ask.

As soon as the compiler sees a number, then it can see it as a integer or float, but never as a double precision floating point number. User horace has the solution by typing the number as a text.

This is your sketch with accurate numbers:

// Testing the fp64lib library
// Forum: https://forum.arduino.cc/t/64-bit-floating-point-library-fp64lib-precision-issue/1162360
// This Wokwi project: https://wokwi.com/projects/374196675432414209

#include <fp64lib.h>

float64_t a = fp64_atof("1.11111111111111111");  // more than enough digits
float64_t b = fp64_atof("1.11111111111111111");
float64_t c;

void setup() 
{
  Serial.begin(9600);

  c = fp64_add( a, b);

  Serial.println( fp64_to_string( a, 20, 0));
  Serial.println( fp64_to_string( b, 20, 0));
  Serial.println( fp64_to_string( c, 20, 0));
}

void loop() {}

Try the sketch in Wokwi simulation:

1 Like

I have run your sketch , and it produces the same result as yours. You have already given this string "3.141592653589793", converting it to ASCII-coded string and then printing it.

@ Koepel
Thank you very much for clear explanation of my error.
Now I understand where the mistake was.
Your example solved the problem.

If you had tried running the code I posted in reply #2, that should have made the problem clear. The result printed by this line: Serial.println(2*1.111111111,15); is exactly the same as what you showed us in the first post, namely 2.222222328186035

@jremington I stepped in because I had to read your post multiple times. I gave it a :heart: because that was the right answer, but maybe a little hard to understand.

@Koepel Your explanation (and complete solution) is much clearer, thanks.

I try to encourage people to think the problem through, and that often doesn't work, especially if they are not inclined to put in some effort.

1 Like

I took the hint.

For constants this I found. I guess you have to figure them out somehow:

#define float64_PI 				((float64_t)0x400921fb54442d18LLU)  // 3.1415926535897932

It looks like they do it a hard way. But being able to, however, seems like it would be an essential feature of such a library.

a7

It computes the Leibniz series approximation to pi. Very slow to converge, but only simple fractions are used, which can be represented exactly.

People that use Arduino and need help are at a very lower level in understanding data type conversion and how to use the specific library functions. If they can do that fast and easy they will not need help or using Arduino. It would have been very helpful for the creators of the library to consider that and create a simple example where you add/subtract two 64 bit numbers. As for the fp64lib it is a very good tool and covers a big hole in Arduino capabilities.

If they can do that fast and easy they will not need help or using Arduino.

Good luck with that idea. It does take some effort to become proficient in any computer language.

As for the fp64lib it is a very good tool and covers a big hole in Arduino capabilities.

Only if you are committed to using the ancient 8 bit AVR Arduinos. All the modern MCUs implement 64 bit floats (double).

The WOKWI tool recommended by @Koepel is very useful simulation tool when you do not need to connect to your hardware. For beginners like me it helps a lot. Did not know it exists. Thanks.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.