Announcing DecimalNumber: floating point arithmetic with arbitrary precision for micropython

Discussion about programs, libraries and tools that work with MicroPython. Mostly these are provided by a third party.
Target audience: All users and developers of MicroPython.
Post Reply
mpy-dev
Posts: 8
Joined: Tue Aug 03, 2021 3:00 pm

Announcing DecimalNumber: floating point arithmetic with arbitrary precision for micropython

Post by mpy-dev » Tue Nov 02, 2021 7:54 pm

The library defines the class DecimalNumber that contains all the functionality for decimal floating point arithmetic with arbitrary precision.

Decimal floating point arithmetic for micropython
Github repository: https://github.com/mpy-dev/micropython-decimal-number

The README.md file contains a description of the funcionality and examples.

This output of the performance test on a Raspberry Pi Pico can give you an idea of what it offers:

Code: Select all

+---------------------------------------------------------------+
|  SYSTEM INFORMATION                                           |
+---------------------------------------------------------------+
Implementation name:           micropython
Implementation version:        1.17.0
Implementation platform:       rp2
CPU frequency:                 125 Mhz

+---------------------------------------------------------------+
|  PERFORMANCE WITH SCALE = 16                                  |
+---------------------------------------------------------------+
Scale (max. decimals):         16
Iterations per test:           1000
Number 1:                      676800226403580.0763143540562581
Number 2:                      -588054433.4243183156555517
Addition (n1 + n2):            1.566 ms
Subtraction (n1 - n2):         1.658 ms
Multiplication (n1 * n2):      1.008 ms
Division (n1 / n2):            1.165 ms
Square root abs(n1):           3.894 ms
Power: (pi/2) ** 15            9.742 ms
DecimalNumber from int:        0.373 ms
DecimalNumber from string:     3.771 ms
Iterations per test:           10
Sine: sin(0.54321)             86.1 ms
Cosine: cos(0.54321)           85.4 ms
Tangent: tan(0.54321)          206.2 ms
Arcsine: asin(0.54321)         267.6 ms
Arccosine: acos(0.65432)       466.6 ms
Arctangent: atan(1.2345)       482.9 ms
Exponential: exp(12.345)       150.3 ms
Natural logarithm: ln(12.345)  150.3 ms

+---------------------------------------------------------------+
|  PERFORMANCE WITH SCALE = 50                                  |
+---------------------------------------------------------------+
Scale (max. decimals):         50
Iterations per test:           400
Number 1:                      -52120532222624450128770268842457267852564.2827656475718343863261636466317618740063535442755
Number 2:                      45521155711104405467504347326435032.84784860134353338157872524608016421466524813041101
Addition (n1 + n2):            2.065 ms
Subtraction (n1 - n2):         2.1925 ms
Multiplication (n1 * n2):      1.55 ms
Division (n1 / n2):            1.45 ms
Square root abs(n1):           11.87 ms
Power: (pi/2) ** 15            11.69 ms
DecimalNumber from int:        0.3825 ms
DecimalNumber from string:     10.64 ms
Iterations per test:           4
Sine: sin(0.54321)             183.25 ms
Cosine: cos(0.54321)           185.5 ms
Tangent: tan(0.54321)          397.25 ms
Arcsine: asin(0.54321)         826.4999 ms
Arccosine: acos(0.65432)       1314.5 ms
Arctangent: atan(1.2345)       1368.75 ms
Exponential: exp(12.345)       280.25 ms
Natural logarithm: ln(12.345)  280.0 ms

+---------------------------------------------------------------+
|  CALCULATING PI                                               |
+---------------------------------------------------------------+
Pi with 300 decimals:          5.838 s
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141274

User avatar
scruss
Posts: 360
Joined: Sat Aug 12, 2017 2:27 pm
Location: Toronto, Canada
Contact:

Re: Announcing DecimalNumber: floating point arithmetic with arbitrary precision for micropython

Post by scruss » Wed Nov 03, 2021 3:17 am

Neat!

Simple demo of a program that's really unfair to floating point numbers.

Binary floating point

Code: Select all

# Broucke precision benchmark

s = 0
x = 0
for n in range(1000):
    s = s+x*x
    x = x+0.00123

print(s, x)
print("Correct results:", "503.54380215", "1.23")
Output:

Code: Select all

503.545 1.230001
Correct results: 503.54380215 1.23
Decimal floating point

Code: Select all

# Broucke precision benchmark - decimal
from mpy_decimal import *

s = DecimalNumber()
x = DecimalNumber()
k = DecimalNumber(123, 5)  # 0.00123

for n in range(1000):
    s = s+x*x
    x = x+k

print(s, x)
print("Correct results:", "503.54380215", "1.23")
Output:

Code: Select all

503.54380215 1.23
Correct results: 503.54380215 1.23

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Announcing DecimalNumber: floating point arithmetic with arbitrary precision for micropython

Post by pythoncoder » Wed Nov 03, 2021 10:53 am

This is most impressive!

A trig function widely used in graphics and robotics is atan2 (four quadrant arctangent). Of course it can readily be implemented by users.

I ran your test on a Pyboard D SF6W. This has hardware 64bit FP, not that this has any bearing on the test results. I had to make a trivial change to line 35 as machine.freq() returns a tuple. The joy of writing portable MP code ;) This was the outcome:

Code: Select all

MicroPython v1.17-75-ge9d71ffb0-dirty on 2021-11-03; PYBD-SF6W with STM32F767IIK
Type "help()" for more information.
>>> import tests.perf_decimal_number

+---------------------------------------------------------------+
|  SYSTEM INFORMATION                                           |
+---------------------------------------------------------------+
Implementation name:           micropython
Implementation version:        1.17.0
Implementation platform:       pyboard
CPU frequency:                 144 Mhz

+---------------------------------------------------------------+
|  PERFORMANCE WITH SCALE = 16                                  |
+---------------------------------------------------------------+
Scale (max. decimals):         16
Iterations per test:           1000
Number 1:                      -28587012411.0450453424443786
Number 2:                      8444451687.1775533021323518
Addition (n1 + n2):            0.5709999999999999 ms
Subtraction (n1 - n2):         0.503 ms
Multiplication (n1 * n2):      0.398 ms
Division (n1 / n2):            0.364 ms
Square root abs(n1):           1.387 ms
Power: (pi/2) ** 15            2.926 ms
DecimalNumber from int:        0.101 ms
DecimalNumber from string:     1.439 ms
Iterations per test:           10
Sine: sin(0.54321)             24.1 ms
Cosine: cos(0.54321)           23.5 ms
Tangent: tan(0.54321)          58.4 ms
Arcsine: asin(0.54321)         75.7 ms
Arccosine: acos(0.65432)       132.2 ms
Arctangent: atan(1.2345)       141.6 ms
Exponential: exp(12.345)       47.4 ms
Natural logarithm: ln(12.345)  48.00000000000001 ms

+---------------------------------------------------------------+
|  PERFORMANCE WITH SCALE = 50                                  |
+---------------------------------------------------------------+
Scale (max. decimals):         50
Iterations per test:           400
Number 1:                      -54286217845712753712657247621852.03846003470775182502466276221462221617377156618756
Number 2:                      54337701734464820071661280425465273585186345463.07403548652677517228173230073537331030278144510542
Addition (n1 + n2):            0.6574999999999999 ms
Subtraction (n1 - n2):         0.6600000000000001 ms
Multiplication (n1 * n2):      0.49 ms
Division (n1 / n2):            0.435 ms
Square root abs(n1):           4.6575 ms
Power: (pi/2) ** 15            3.5275 ms
DecimalNumber from int:        0.11 ms
DecimalNumber from string:     3.9175 ms
Iterations per test:           4
Sine: sin(0.54321)             52.0 ms
Cosine: cos(0.54321)           53.50000000000001 ms
Tangent: tan(0.54321)          116.5 ms
Arcsine: asin(0.54321)         237.5 ms
Arccosine: acos(0.65432)       378.75 ms
Arctangent: atan(1.2345)       403.75 ms
Exponential: exp(12.345)       89.50000000000001 ms
Natural logarithm: ln(12.345)  90.75000000000001 ms

+---------------------------------------------------------------+
|  CALCULATING PI                                               |
+---------------------------------------------------------------+
Pi with 300 decimals:          1.725 s
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141274
>>> 
Peter Hinch
Index to my micropython libraries.

mpy-dev
Posts: 8
Joined: Tue Aug 03, 2021 3:00 pm

Re: Announcing DecimalNumber: floating point arithmetic with arbitrary precision for micropython

Post by mpy-dev » Wed Nov 03, 2021 5:19 pm

Thank you both for your testing and comments.

When I have time, I will add atan2(). I have no doubt that many developers can implement that function, but I think it is better to include it in the library, in the collection of tests and in the performance test.

A library needs to be useful. If you know of any other mathematical function that is widely used and needed by microcontrollers' developments, let me know.

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Announcing DecimalNumber: floating point arithmetic with arbitrary precision for micropython

Post by Roberthh » Wed Nov 03, 2021 8:11 pm

test figures for a Teensy 4.1:

Code: Select all

+---------------------------------------------------------------+
|  SYSTEM INFORMATION                                           |
+---------------------------------------------------------------+
Implementation name:           micropython
Implementation version:        1.17.0
Implementation platform:       mimxrt
CPU frequency:                 600 Mhz

+---------------------------------------------------------------+
|  PERFORMANCE WITH SCALE = 16                                  |
+---------------------------------------------------------------+
Scale (max. decimals):         16
Iterations per test:           1000
Number 1:                      17364141.588507675777544
Number 2:                      45403805481532.2666065708430204
Addition (n1 + n2):            0.212 ms
Subtraction (n1 - n2):         0.172 ms
Multiplication (n1 * n2):      0.108 ms
Division (n1 / n2):            0.116 ms
Square root abs(n1):           0.398 ms
Power: (pi/2) ** 15            1.75 ms
DecimalNumber from int:        0.03 ms
DecimalNumber from string:     0.485 ms
Iterations per test:           10
Sine: sin(0.54321)             8.1 ms
Cosine: cos(0.54321)           7.9 ms
Tangent: tan(0.54321)          19.3 ms
Arcsine: asin(0.54321)         24.9 ms
Arccosine: acos(0.65432)       43.3 ms
Arctangent: atan(1.2345)       46.6 ms
Exponential: exp(12.345)       16.3 ms
Natural logarithm: ln(12.345)  16.3 ms

+---------------------------------------------------------------+
|  PERFORMANCE WITH SCALE = 50                                  |
+---------------------------------------------------------------+
Scale (max. decimals):         50
Iterations per test:           400
Number 1:                      -76555145458785411342836812226355222222.56467681088330125167278871222371800251872433545216
Number 2:                      -48487110413130740162544841268554338257.04672246841012630187884547875870821007757777035406
Addition (n1 + n2):            0.2375 ms
Subtraction (n1 - n2):         0.2325 ms
Multiplication (n1 * n2):      0.1675 ms
Division (n1 / n2):            0.14 ms
Square root abs(n1):           1.3375 ms
Power: (pi/2) ** 15            2.0275 ms
DecimalNumber from int:        0.0325 ms
DecimalNumber from string:     1.9325 ms
Iterations per test:           4
Sine: sin(0.54321)             17.75 ms
Cosine: cos(0.54321)           17.0 ms
Tangent: tan(0.54321)          37.75 ms
Arcsine: asin(0.54321)         76.5 ms
Arccosine: acos(0.65432)       123.0 ms
Arctangent: atan(1.2345)       132.25 ms
Exponential: exp(12.345)       29.5 ms
Natural logarithm: ln(12.345)  30.25 ms

+---------------------------------------------------------------+
|  CALCULATING PI                                               |
+---------------------------------------------------------------+
Pi with 300 decimals:          0.54 s
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141274
And for another MIMXRT board:

Code: Select all

+---------------------------------------------------------------+
|  SYSTEM INFORMATION                                           |
+---------------------------------------------------------------+
Implementation name:           micropython
Implementation version:        1.17.0
Implementation platform:       mimxrt
CPU frequency:                 996 Mhz

+---------------------------------------------------------------+
|  PERFORMANCE WITH SCALE = 16                                  |
+---------------------------------------------------------------+
Scale (max. decimals):         16
Iterations per test:           1000
Number 1:                      48727664634402.5345521171702275
Number 2:                      -41701170508186.3465642547850136
Addition (n1 + n2):            0.119 ms
Subtraction (n1 - n2):         0.08599999999999998 ms
Multiplication (n1 * n2):      0.06600000000000001 ms
Division (n1 / n2):            0.063 ms
Square root abs(n1):           0.275 ms
Power: (pi/2) ** 15            1.153 ms
DecimalNumber from int:        0.018 ms
DecimalNumber from string:     0.408 ms
Iterations per test:           10
Sine: sin(0.54321)             4.4 ms
Cosine: cos(0.54321)           4.4 ms
Tangent: tan(0.54321)          10.6 ms
Arcsine: asin(0.54321)         14.0 ms
Arccosine: acos(0.65432)       24.3 ms
Arctangent: atan(1.2345)       26.0 ms
Exponential: exp(12.345)       8.9 ms
Natural logarithm: ln(12.345)  8.9 ms

+---------------------------------------------------------------+
|  PERFORMANCE WITH SCALE = 50                                  |
+---------------------------------------------------------------+
Scale (max. decimals):         50
Iterations per test:           400
Number 1:                      7841427756076425812504087.08185156485662145262856783525141851306002723660405
Number 2:                      -870261011570324722588353348005007425813701860380.32847714741388751654240845321451257162401531527385
Addition (n1 + n2):            0.1525 ms
Subtraction (n1 - n2):         0.13 ms
Multiplication (n1 * n2):      0.105 ms
Division (n1 / n2):            0.08 ms
Square root abs(n1):           0.8449999999999999 ms
Power: (pi/2) ** 15            1.2775 ms
DecimalNumber from int:        0.0225 ms
DecimalNumber from string:     1.01 ms
Iterations per test:           4
Sine: sin(0.54321)             9.5 ms
Cosine: cos(0.54321)           9.25 ms
Tangent: tan(0.54321)          20.75 ms
Arcsine: asin(0.54321)         44.0 ms
Arccosine: acos(0.65432)       70.0 ms
Arctangent: atan(1.2345)       75.25 ms
Exponential: exp(12.345)       17.25 ms
Natural logarithm: ln(12.345)  17.0 ms

+---------------------------------------------------------------+
|  CALCULATING PI                                               |
+---------------------------------------------------------------+
Pi with 300 decimals:          0.315 s
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141274

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Announcing DecimalNumber: floating point arithmetic with arbitrary precision for micropython

Post by pythoncoder » Thu Nov 04, 2021 11:45 am

That is fast. :D
Peter Hinch
Index to my micropython libraries.

mpy-dev
Posts: 8
Joined: Tue Aug 03, 2021 3:00 pm

Re: Announcing DecimalNumber: floating point arithmetic with arbitrary precision for micropython

Post by mpy-dev » Thu Nov 04, 2021 6:12 pm

Thanks for the tests. There are quite fast microcontrollers.

I have added to DecimalNumber class the function atan2(), the 2-argument arctangent.

Post Reply