PDA

View Full Version : Big Numbers and how to print them



Constantin
01-12-2013, 05:14 AM
As a 32-bit microprocessor, the Teensy 3.0 can handle much bigger numbers than the Arduino can without the addition of Nick Gammons excellent BigNumbers (http://www.gammon.com.au/forum/?id=11519) library. However, BigNumbers doesn't yet work on the Teensy ARM (compiler error with every example).

Understandably, the standard Serial.print command seems to be unhappy with printing anything bigger than 2^32 because that's the biggest number that one can easily define in the IDE (2^64 is available but cannot be printed with default commands...)

How does one print larger numbers than 2^64 when the IDE Serial.print command is limited to 2^32 bits only? Write one's own serial print command or appropriate parts of Nick Gammons code? Just wondering... Many thanks and have a great weekend.

Nantonos
01-12-2013, 08:43 AM
32 bit and 2^32 are irrelevant in this case - it seems to be a binary coded decimal library, so each digit is 8 bits and you can have as many digits as you can fit (and process, and convert to strings) in memory.

http://en.wikipedia.org/wiki/Binary_coded_decimal

Obviously, as with any non-standard type, Serial.print won't know how to print it unless extended to do so. But Serial.print can print character strings just fine, so convery bcd to a string and print that.

Nantonos
01-12-2013, 09:06 AM
Confirming that Teensy 3.0 gives compile errors with the BigNumbers library. Using the 'Powers' example supplied with the library:




f:/arduino/arduino-1.0.3-teensy-beta10/hardware/tools/arm-none-eabi/bin/../lib/gcc/arm-none-eabi/4.4.1/../../../../arm-none-eabi/lib/thumb2\libc.a(lib_a-exit.o): In function `exit':
exit.c:(.text+0x1c): undefined reference to `_exit'
collect2: ld returned 1 exit status


The same example compiles and runs without error on Teensy 2.0. Tail end of output from 'Powers':


3^296 = 16900182599825725431027904615072631600797987114239 18968783706050350234533055544155479014890810974585 040129437538246840034734725095872787340321
3^297 = 50700547799477176293083713845217894802393961342717 56906351118151050703599166632466437044672432923755 120388312614740520104204175287618362020963
3^298 = 15210164339843152887925114153565368440718188402815 27071905335445315211079749989739931113401729877126 5361164937844221560312612525862855086062889
3^299 = 45630493019529458663775342460696105322154565208445 81215716006335945633239249969219793340205189631379 6083494813532664680937837577588565258188667
3^300 = 13689147905858837599132602738208831596646369562533 74364714801900783689971774990765938002061556889413 88250484440597994042813512732765695774566001

Nantonos
01-12-2013, 09:20 AM
As another point of comparison, using Arduino 1.5 (original release) and Arduino Due, the BigNumbers example 'Powers' compiles and runs correctly (once I remembered to set the baud rate in the serial monitor :) ).

So this is not necessarily an AVR vs. ARM issue and not necessarily a fault in the ARM gcc standard C library, otherwise Due would also be affected.

(Oops, forgot to mention that the Teensy 2.0 and 3.0 tests were done with beta 10 Teensyduino).

PaulStoffregen
01-12-2013, 12:51 PM
I've added _exit() to mk20dx128.c. A copy is attached. Just rename from .txt to .c and replace the mk20dx128.c in hardware/teensy/cores/teensy3.

This will be in beta 11, which I'm planning to release very soon (only the new toolchain and bug fixes, like this one).

I ran the BigNumber Powers example on a Teensy 3.0 and it seems to work.

Constantin
01-12-2013, 03:05 PM
32 bit and 2^32 are irrelevant in this case - it seems to be a binary coded decimal library, so each digit is 8 bits and you can have as many digits as you can fit (and process, and convert to strings) in memory.

http://en.wikipedia.org/wiki/Binary_coded_decimal

Obviously, as with any non-standard type, Serial.print won't know how to print it unless extended to do so. But Serial.print can print character strings just fine, so convery bcd to a string and print that.

True enough, but for someone as new to Arduinos and programming in general, it's hard to write a function like Nick did to handle printing large numbers. I'm OK re: logic, math, all that but the nuances of how functions interpret what they need to print, etc. is sometimes lost on me. Also, there is a huge difference between the 8-bit Arduino and a 32-bit ARM processor in that the latter can handle much larger numbers just fine while the Arduino needs the bignumbers library. The IDE still needs to catch up, as best as I can tell, to reflect the much greater range of variables that might be thrown at Serial.print, for example.

For my application, I use a least squares approach to help correct the INL and other imperfections of my ADC. The best fit correction for the data requires a function ax^2+bx+c and solving for that requires a number of summations, multiplications, etc. that result in very large numbers when exhausting the range of a 16 bit ADC. I don't recall the details offhand right now, but the largest number within that series of equations is something in the vicinity of 1.9x10^25 (resulting from sum_x^3*sum_x^4, IIRC).

In excel, I was able to correct offsets, INL, etc. to a very small number indeed, making the DAQ system the smallest contributor to variability. On the Arduino, even a uint64 couldn't come close to hacking the numbers above and I had to right-shift all inputs into the correction formula by 6 bits, resulting in much lower accuracy re: the correction factors. Bignumbers came to the rescue, though on a 32-bit microprocessor, bignumbers is not needed - it can handle them just fine. Just not all the other parts of the IDE!

Constantin
01-12-2013, 03:06 PM
Thank you, Paul!

I create nothing but trouble, it seems! ;) Do you suppose that the Arduino IDE will be re-written to allow the Due and so on to Serial.print larger numbers than is presently the case?

PaulStoffregen
01-12-2013, 04:34 PM
I create nothing but trouble, it seems! ;)


Reproducible bug reports are always very welcome! :)

Thanks!



Do you suppose that the Arduino IDE will be re-written to allow the Due and so on to Serial.print larger numbers than is presently the case?


I believe there's 2 ways to look at this question....

#1: Arduino does have an (obscure) interface for classes like BigNumber to print. I've modified BigNumber to use it. The code is attached. I modified the Factorials example to show how it's used. You can just pass a BigNumber object to Serial.print(), or any of the Arduino XYZ.print() functions.

#2: Inside the print function, floating point numbers are printed by shifting the integer portion of the mantissa into a 32 bit integer. The unsigned integer code is used to print the left side. Then a simple loop generates 8 digits from the fractional portion. This is relatively fast and doesn't require a lot of code, but the downside is you only get a printable range of approx 10e-7 to 10e9. Single precision float's range is approx 10e-44 to 10e38, but code capable of formatting numbers over that entire range is much larger and much slower. The decision was made to trade range for speed and small size.

Constantin
01-12-2013, 07:43 PM
Absolutely. Does serial.Print in Arduino 1.5 feature the ability to handle larger numbers than it did as of 1.03? That is, without requiring an external library like big numbers.... Seems like a pretty standard problem given how big a long long integer can get on a 32 bit microprocessor.

Jp3141
01-13-2013, 03:09 AM
Absolutely. Does serial.Print in Arduino 1.5 feature the ability to handle larger numbers than it did as of 1.03? That is, without requiring an external library like big numbers.... Seems like a pretty standard problem given how big a long long integer can get on a 32 bit microprocessor.

Do you really need big INTEGERS ? can't you use floating point & sprintf().

Nantonos
01-13-2013, 01:57 PM
Reproducible bug reports are always very welcome! :)
#1: Arduino does have an (obscure) interface for classes like BigNumber to print. I've modified BigNumber to use it. The code is attached. I modified the Factorials example to show how it's used. You can just pass a BigNumber object to Serial.print(), or any of the Arduino XYZ.print() functions.

Paul, did you tell Nick Gammon about tha useful modification? He might want to update the library on his site.

PaulStoffregen
01-13-2013, 02:43 PM
I have not. I didn't see an obvious way to contact Nick... and then I got distracted by the WS2811 LEDs ;-)

(and today I'm looking at the missing USB types....)

If you know a way to contact Nick, could you please let him know?

Nantonos
01-13-2013, 03:09 PM
If you know a way to contact Nick, could you please let him know?

Done (he is a moderator on the Arduino forum, I sent a pm with a summary and link to this thread).