Arbitrary precision (big number) library port for Arduino

Hi Nick, your library BigNumber this great, could you help me or tell me how to give more precision to my projects, when I divide 10/3 = 3.00 to 2 decimal Arduino anything else, as I can get more decimal places, 4 or 5 after point.

You might have to show your code. By default the big number library gives you no decimal places. Read this thread:

http://www.gammon.com.au/forum/?id=11519

Scroll down to where it talks about "setScale" which lets you set the number of decimal places.

when I divide 10/3 = 3.00 to 2 decimal Arduino anything else

Please explain what this means, and show your code.

float a = 10.0/3.0;

results in a containing 3.333333.

Serial.print(a);

results in 3.33 being printed.

Serial.print(a, 4);

results in 3.3333 being printed.

We need to know exactly what your problem is, though.

Thank you very much for your quick responses, if the problem is not knowing what to Serial.println (v, 4 or 3 or 2).

Thank you very much! > PaulS and Nick Gammon

my problem is solved (y)

Thanks to suggestions from Paul Stoffregen, the library has now been modified to allow you to directly print big numbers.

For example, the Factorials example now looks like this:

// BigNumber test: factorials
#include "BigNumber.h"

void setup ()
{
  Serial.begin (115200);
  while (!Serial) ;
  delay(500);
  Serial.println ();
  BigNumber::begin ();  // initialize library
 
  //factorials
  BigNumber fact = 1;

  for (int i = 2; i <= 200; i++)
  {
    Serial.print(i);
    Serial.print("! = ");
    fact *= i;
    Serial.println (fact);
  }

}  // end of setup

void loop () { }

This was done by deriving the BigNumber class from the Printable class. This means that you can now print big numbers from any class derived from Stream (eg. Serial, Serial1, etc.).

New library downloadable from the same place as the old one:

http://www.gammon.com.au/Arduino/BigNumber.zip

Ok, so its been a few years since I have programmed in C++ and etc; so I am extremely rusty. Anyhow, I am trying to use your library for conversions. That is, I have an absolute pressure sensor (PSI) and a temperature sensor; in the end I want to multiply absolute pressure * temperature however before that I need convert pressure (PSI) to Pascal and temp (Celsius) to kelvin. Well, 1 PSI = 6894.75729 Pa; and °K = °C+273.15. Multiplying those numbers together you get a large number; example: 77 PSI, 25C. 77 PSI = 530896.31133000006 Pa, 25 C = 298.15; therefore multiplied = 158286735.22303951. I've been messing around w/ the library and for some reason I can't get any sort of decimal.

BigNumber::setScale (8);
  
  BigNumber pascal = 689475729/100000;
  BigNumber pressure = 77.5;
  BigNumber temp = 25.0;
  BigNumber kelvin = 273.15;
  
  BigNumber toPascal, toKelvin, AbsTempPress;
  toPascal = pascal*pressure;
  toKelvin = temp + kelvin;
  
  AbsTempPress = toPascal*toKelvin;

Serial.println("Pascal: ");
  Serial.print(pascal);
  Serial.println();
  Serial.println("Kelvin: ");
  Serial.print(kelvin);
  Serial.println();
  Serial.println("Pressure: ");
  Serial.print(pressure);
  Serial.println();
    Serial.println("Temperature: ");
  Serial.print(temp);
  Serial.println();

  Serial.println("To Pascal: ");
  Serial.print(toPascal);
  Serial.println();
  Serial.println("To Kelvin: ");
  Serial.print(toKelvin);
  Serial.println();
  Serial.println("Absolute Pressure * Temp: ");
  Serial.print(AbsTempPress);
  Serial.println();

*****************************OUTPUT

Pascal: 
6894
Kelvin: 
273
Pressure: 
77
Temperature: 
25
To Pascal: 
530838
To Kelvin: 
298.00000000
Absolute Pressure * Temp: 
158189724.00000000

Please edit your post, select the code, and put it between [code][/code] tags.

You can do that by hitting the # button above the posting area.

Do you need Big numbers with your pressure and temp calcs? Is the 32bit single precision float not precise enough? What is your pressure and temperature converters precision/accuracy?

Your problem is here:

  BigNumber pascal = 689475729/100000;
  BigNumber pressure = 77.5;
  BigNumber temp = 25.0;
  BigNumber kelvin = 273.15;

The compiler takes 689475729/100000, does the division as an integer, and puts the result (6894) into pascal.

You have to pass them as strings, like this, to have the BigNumber library do the conversion:

  BigNumber pascal ("6894.75729");
  BigNumber pressure ("77");
  BigNumber temp ("25.0");
  BigNumber kelvin ("273.15");

Doing that, the sketch outputs:

Pascal: 
6894.75729
Kelvin: 
273.15
Pressure: 
77
Temperature: 
25.0
To Pascal: 
530896.31133
To Kelvin: 
298.15000000
Absolute Pressure * Temp: 
158286735.22303950

Which looks like what you wanted.

Full sketch:

#include <BigNumber.h>

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

  BigNumber::begin ();

  BigNumber::setScale (8);
  
  BigNumber pascal ("6894.75729");
  BigNumber pressure ("77");
  BigNumber temp ("25.0");
  BigNumber kelvin ("273.15");
  
  BigNumber toPascal, toKelvin, AbsTempPress;
  toPascal = pascal*pressure;
  toKelvin = temp + kelvin;
  
  AbsTempPress = toPascal*toKelvin;

  Serial.println("Pascal: ");
  Serial.print(pascal);
  Serial.println();
  Serial.println("Kelvin: ");
  Serial.print(kelvin);
  Serial.println();
  Serial.println("Pressure: ");
  Serial.print(pressure);
  Serial.println();
    Serial.println("Temperature: ");
  Serial.print(temp);
  Serial.println();

  Serial.println("To Pascal: ");
  Serial.print(toPascal);
  Serial.println();
  Serial.println("To Kelvin: ");
  Serial.print(toKelvin);
  Serial.println();
  Serial.println("Absolute Pressure * Temp: ");
  Serial.print(AbsTempPress);
  Serial.println();
  
  }  // end of setup

void loop () { }

pito: Do you need Big numbers with your pressure and temp calcs? Is the 32bit single precision float not precise enough? What is your pressure and temperature converters precision/accuracy?

As accurate as I can get it. The temp/pressure sensors have an accuracy of .2%; but none the less I do not want to introduce mathematical error and have it propagate through calculations for instance, say I round off the conversions which will introduce say a 1% error, after calculations that 1% error will propagate and in the end be larger than 5%.

[quote author=Nick Gammon link=topic=85692.msg1126864#msg1126864 date=1361393124] Your problem is here:

  BigNumber pascal = 689475729/100000;
  BigNumber pressure = 77.5;
  BigNumber temp = 25.0;
  BigNumber kelvin = 273.15;

The compiler takes 689475729/100000, does the division as an integer, and puts the result (6894) into pascal.

You have to pass them as strings, like this, to have the BigNumber library do the conversion:

  BigNumber pascal ("6894.75729");
  BigNumber pressure ("77");
  BigNumber temp ("25.0");
  BigNumber kelvin ("273.15");

Ok, I understand that; so now that would leave me with converting the floats from the pressure/temp sensors to strings

The temp/pressure sensors have an accuracy of .2%;

That's 3digits, imho. Big numbers are used when you want to calculate how the distance between Jupiter and Earth changes with Planck length precision :)

pito:

The temp/pressure sensors have an accuracy of .2%;

That's 3digits, imho. Big numbers are used when you want to calculate how the distance between Jupiter and Earth changes with Planck length precision :)

And yet when your in the planetary scale, the error shots externally high. Also, there is obviously another use for numbers that are bigger then what the data type can provide, also the name of the library "...precision...". Oh, and if you go in the opposite direction, atomic/nuclear scale large numbers there too which use planks constant, ideal gas law, conversions, etc. Guess it all depends on how you define large. Thinking in a distance terms, or in span/number of digits.

lordofentropy: Ok, I understand that; so now that would leave me with converting the floats from the pressure/temp sensors to strings

I would be a little surprised if the sensors didn't have an option to return some sort of integer with a scaling factor.

I think the real question is what are you going to do with the values you get? Suppose you get temperature and pressure to 12 decimal places. So what? What are you going to do with the values? Keeping in mind that they are no more accurate than the sensor in the first place.

lordofentropy:
Ok, I understand that; so now that would leave me with converting the floats from the pressure/temp sensors to strings

Here is one way:

#include <FormatDouble.h>

...

  float sensorReading = 77.12345;   
  char buf [20];
  fmtDouble (sensorReading, 6, buf, sizeof buf);  
  BigNumber pressure = BigNumber (buf);

Library here: http://gammon.com.au/Arduino/FormatDouble.zip

PaulS: I think the real question is what are you going to do with the values you get? Suppose you get temperature and pressure to 12 decimal places. So what? What are you going to do with the values? Keeping in mind that they are no more accurate than the sensor in the first place.

Ok, so there seems to be some confusion on whats going on here, I assume it is due to the code I posted. My end game/goal is not to expand the precision of the actual sensors, I have already calibrated them with a multi-meter that has extremely high accuracy (most multi-meters are .5% to 1% accurate which propagated through calibration expanding the error to 8% then plus the accuracy of sensor). Anyhow, I will be using the library specifically for the conversion/ pascals * temp b/c there is no data type that can hold that number. I know in my code I was using the library for temperatures/pressure and doing all the calculations with it. That code was just me playing with the library and getting to know it; it by no means is my finalized code...hence all the serial outs verifying everything. In my c++ days I used couts to help debug and etc. and I am doing the same here; not just to to show information but to show where a program would hang up or not exactly perform to design.

So the whole point here was to do exact conversions so I would not introduce even more error; is it really so wrong for someone to want to convert b/w units properly w/o adding more error within the calculations? Also, depending on the extent of calculations that said error that started out small can torpedo out of control in the end.

I don't see any problem with wanting greater precision. I hope I have answered the question about how to achieve that.

Under some circumstances, using "float" would be adequate, probably that is what prompted the questions.

Also, is there a real usage of this library ?

Mathematics, especially statistics / combinatorics uses large numbers, think of holding intermediate results. Economics - to display national debts of some states ;)

When you want precision more than 7/10 digits float/long does not work anymore...;

Economics - to display national debts of some states smiley-wink

Do you think a national bank of an EU state know they have 6.892.123.323.434,43Euro depth? They are happy to know it with 5 digit precision :) But you are right, bankers and accountants like it. Therefore the better machines still have processors which understand binary coded decimals http://en.wikipedia.org/wiki/Binary-coded_decimal or packed decimals.