Go Down

Topic: Arbitrary precision (big number) library port for Arduino (Read 38682 times) previous topic - next topic

Pyrotrons

Quote
You can cast a big number into a long, or get a character array returned.
Char array would be best, as my BigNumber output could potentially be a very small number (a few picofarads, 3x10E-12).

Quote
What do you want to do so many digits of precision?
I'm squaring two frequencies in the Mhz range, dividing them, subtracting 1.0 from the result, then multiplying by a capacitor value in the pF range.  Very big, to very small.

Code: [Select]

  BigNumber X = F1;  //define the first frequency measurement 
  BigNumber Y = F2;  //define the second frequency measurement
  BigNumber one = "1"; //don't laugh
  BigNumber Cx = ((  ((X*X)/(Y*Y)) - one) * Ceff);


  • X and Y are frequency counts, each count is ~1 Megahertz, with Y being slightly lower than X.
  • Ceff is a .000000000390 Farad "effective" reference capacitor value (390 picofarads).
  • Cx is the capacitor being measured. The one I want the value of.


Quote
If you want help you need to post code, not just say that something, which you're not disclosing, did not compile.
You're absolutely right, I'll remove my statement above. I chose this due to my lack of converting confidence...didn't mean to point fingers, I won't do it again.

Pyrotrons

I've reduced my problem to its simplest form...converting a BigNumber variable into a printable format (not speaking of Serial.println...).  See errors at bottom.  Regards,  - Pyrotrons

Code: [Select]

#include <stdint.h>
#include <BigNumber.h>
#include <TouchScreen.h>
#include <TFT.h>

//Touchscreen setup:
#ifdef MEGA
  #define YP A2   // must be an analog pin, use "An" notation!
  #define XM A1   // must be an analog pin, use "An" notation!
  #define YM 54   // can be a digital pin, this is A0
  #define XP 57   // can be a digital pin, this is A3
#endif

void setup()
{
  Serial.begin(57600);
  delay(100);
  BigNumber::begin ();  //init BigNumber lib
  BigNumber::setScale (15);  //set precision
  Tft.init();  //init TFT lib
  Tft.setDisplayDirect(UP2DOWN); //set text direction
 
  String tempstr_A = "Big ol string to display";  //random stuff to test printing to TFT screen
  char buf_A[20];
  tempstr_A.toCharArray(buf_A, 15);
  Tft.drawString(buf_A,220,20,2,WHITE);  //this works

  BigNumber x = "44444444444444444444444444444";
  BigNumber y = "2";
  BigNumber z;
  z = x * y;
  Serial.println(z); // This works. I get 8888888...etc.

//Beginning attempt at converting BigNumber variable "z" into a printable (on my display) format
//----------------------------------------------------------------------------------------------

  String tempstring = z;  //Error: "conversion from 'BigNumber' to nonscalar type 'String' requested

  char buf_B[20];
  z.toCharArray(buf_B, 20); //Error: 'class BigNumber has no member named 'toCharArray'
} //END of setup

void loop()
{
  while(1);
}


nickgammon

To get the string from a big number just call the  toString function, eg.

Code: [Select]

char * buf = z.toString ();

// use buf

free (buf);


However why bother?

Just make sure that your end result is a number in pF can be expressed in a long.

You are not going to get a number with 10 digits in a picofarad range (that cannot be expressed in microfarads for example).
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

refsmmat

Hi,

Firstly, thanks Nick for the library.
I am using it on a DUE to implement an "astronomy" application.


I am parsing a csv & looking to transpose values from a char array into a bignumber. My intent is to run the Matlab model (link below) on a due to generate accurate planet positions wrt time.

My thought on the method is  -
1)using pointers, write the parsed char array containing the bignumber to a memory location
2) read the bignumber from the same location.

My questions are:
a) will this work?
b)is this the tidiest method?


My orig code  (in Matlab) is here:

http://au.mathworks.com/matlabcentral/fileexchange/26114-solar-system-model--planetary-n-body-modelling-

I can post the parsing elements(currently incomplete) here if it helps

Many thanks
Stephen

nickgammon

I can't say whether code that is merely described will work. You could post it. You could try it and see what happens which is what I usually do.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

NiceAntoine

I cannot figure how to use an external eeprom chip to go further with even bigger numbers , after all ram is the limiting factor, maybe using an eeprom chip as ram or assigning variables to it might help? any idea?

nickgammon

#141
Feb 27, 2015, 04:04 am Last Edit: Feb 27, 2015, 04:04 am by Nick Gammon
I don't see how that would help. Get a chip with more RAM if you must.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

NiceAntoine

I don't see how that would help. Get a chip with more RAM if you must.
After reading docs about how to efficiently make operations with big numbers, an authors said " normally you may use big numbers until your RAM is full, but if you are smart enough you can calculate big numbers until your RAM and your HDD are full."
After reading some math and programming info, I know how to proceed in order to use an SD card to go MUCH further with big numbers.
It will be great to have a project that allows our humble arduino UNO to do- for instance- 4096bit RSA encryption :D.
As soon as I finish an urgent work, I will for sure puts my hands on it.

I might be a newbie in programation, but numbers and me, we are good old friends !

By the way, if someone do the project , I will be happy to try to improve it.

Cheers!

flok99

I very much like this library and its c++ wrapper. There's only one thing: it uses so much memory. Not because of the code-size or that large numbers take large amounts of memory, but that it uses 1 byte to store 1 digit. That is over 50% waste (1 digit fits in less than 4 bits).
Maybe all accesses to each digit can be wrapped in a function which divides the index in the char by 2, then checks the original lsb if it was 0 or 1 and then picks the lower or upper nibble. Would use slightly more cpu but with the advantage of almost a doubling in memory efficiency.

p.s. @nick gammon: have you seen my patches at github?

nickgammon

Quote
...  it uses 1 byte to store 1 digit ...
As did the original library. I'm reluctant to fiddle too much, because I might introduce bugs without realizing it. Plus, some people would want speed more than memory compactness.

Quote
... have you seen my patches at github?
I got a pull request, yes. I have to take a little while to examine it. Thanks. :)
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

odometer

Maybe modify it so it uses base 100 instead of base 10?

odometer

Char array would be best, as my BigNumber output could potentially be a very small number (a few picofarads, 3x10E-12).

I'm squaring two frequencies in the Mhz range, dividing them, subtracting 1.0 from the result, then multiplying by a capacitor value in the pF range.  Very big, to very small.

Code: [Select]

  BigNumber X = F1;  //define the first frequency measurement 
  BigNumber Y = F2;  //define the second frequency measurement
  BigNumber one = "1"; //don't laugh
  BigNumber Cx = ((  ((X*X)/(Y*Y)) - one) * Ceff);


  • X and Y are frequency counts, each count is ~1 Megahertz, with Y being slightly lower than X.
  • Ceff is a .000000000390 Farad "effective" reference capacitor value (390 picofarads).
  • Cx is the capacitor being measured. The one I want the value of.


What datatype are F1 and F2?

With a bit of algebra, you might be able to do this well enough without BigNumber.

flok99

Maybe modify it so it uses base 100 instead of base 10?
That may nog work.

The number.h file says:

Code: [Select]
/* The base used in storing the numbers in n_value above.
   Currently this MUST be 10. */

#define BASE 10


Also a quick test shows that it doesn't work with other BASE values. In this test I tried BASE = 255.

Code: [Select]
#include <stdint.h>
#include <stdio.h>

#include "BigNumber.h"

int main(int argc, char *argv[])
{
uint64_t i = 812389l * 181092947l;
printf("%lu\n", i);

BigNumber bn1(812389);
BigNumber bn2(181092947);
BigNumber bn = bn1 * bn2;

long bnl = bn;
printf("%ld\n", bnl);

return 0;
}


Result:

Code: [Select]
147117918120383
132421247473087

aarg

Any reason why bignum calculations can not be done in binary? Conversion is too unwieldy? Mathematicians want truncation to be in decimal?
  ... with a transistor and a large sum of money to spend ...
Please don't PM me with technical questions. Post them in the forum.

odometer

#149
Sep 09, 2015, 09:21 pm Last Edit: Sep 09, 2015, 11:21 pm by odometer Reason: mistake in denominator
I'm squaring two frequencies in the Mhz range, dividing them, subtracting 1.0 from the result, then multiplying by a capacitor value in the pF range.  Very big, to very small.

Code: [Select]

  BigNumber X = F1;  //define the first frequency measurement  
  BigNumber Y = F2;  //define the second frequency measurement
  BigNumber one = "1"; //don't laugh
  BigNumber Cx = ((  ((X*X)/(Y*Y)) - one) * Ceff);


  • X and Y are frequency counts, each count is ~1 Megahertz, with Y being slightly lower than X.
  • Ceff is a .000000000390 Farad "effective" reference capacitor value (390 picofarads).
  • Cx is the capacitor being measured. The one I want the value of.

So try this:

Code: [Select]

  float f2_f = F2;  // second frequency (we expect this to be lower)
  float d_f  = (F1 - F2);  // difference between the two frequencies
  float q_f  = (((2 * f2_f) + d_f) * d_f) / (f2_f * f2_f); // if my algebra is correct
  float c_f  = q_f * 390.0; // capacitance in picofarads  


The algebra I am using is:

(a+b)^2 = (a^2) + (2*a*b) + (b^2)
Therefore:
(a+b)^2 - (a^2) = (2*a*b) + (b^2) = ((2*a)+b)*b

Go Up