Dealing with numbers outside of uint256 range - decimal

i am trying to build compound formula with solidity but I have came across a problem, given enough days, the amount is compounded, amount will overflow uint256 range.
I have read that as long as final result is in the range of uint256, it should be fine but it does not seem to be the case. here is the calculation that i am trying to do
(100 * (100+8)^100) * 10^(6 - 2*100)
as a formula it looks like this:
( BASE * ( (1 * 10^MULTIPLIER) + (YIELD * 10^MULITPLIER) ) ^ COMPOUNDED_DAYS ) * ( 10 ^ (DECIMALS - MULTIPLIER * COMPOUNDED_DAYS) )
as mentioned this is compound formula with 6 decimals, but when i run this in playground i get "0" as a result. what's the problem, and if there is problem how can i fix it?

The reason is that your number becomes smaller than one and the integer turns it into zero

The caret sign ^ represents a bitwise XOR - not an exponential multiplication. If you want to calculate "to the power of", use two asterisks **.
Example: "10 to the power of 2" in Solidity: 10 ** 2

Related

why is np.exp(x) not equal to np.exp(1)**x

Why is why is np.exp(x) not equal to np.exp(1)**x?
For example:
np.exp(400)
>>>5.221469689764144e+173
np.exp(1)**400
>>>5.221469689764033e+173
np.exp(400)-np.exp(1)**400
>>>1.1093513018771065e+160
This is optimisation of numpy that raise this diff.
Indeed, you have to understand how is calculated the Euler number in math:
e = (1/n)**n with n == inf.
I think numpy stop at a certain order:
You have in the numpy exp documentation here that is not very clear about how the Euler number is calculated.
Because of this order that is not equal to infinity, you have this small difference in the two calculations.
Indeed the value np.exp(400) is calculated using this: (1 + 400/n)**n
>>> (1 + 400/n)**n
5.221642085428121e+173
>>> numpy.exp(400)
5.221469689764144e+173
Here you have n = 1000000000000 wich is very small and raise this difference at 10e-5.
Indeed there is no exact value of the Euler number. Like Pi, you can only have an approched value.
It looks like a rounding issue. In the first case it's internally using a very precise value of e, while in the second you get a less precise value, which when multiplied 400 times the precision issues become more apparent.
The actual result when using the Windows calculator is 5.2214696897641439505887630066496e+173, so you can see your first outcome is fine, while the second is not.
5.2214696897641439505887630066496e+173 // calculator
5.221469689764144e+173 // exp(400)
5.221469689764033e+173 // exp(1)**400
Starting from your result, it looks it's using a value with 15 digits of precision.
2.7182818284590452353602874713527 // e
2.7182818284590450909589085441968 // 400th root of the 2nd result

Display double in 2 decimal places in RPG?

When declaring floating-point variable, I don't understand the amount of precision needed for the stored object in RPG ??
In my exercice, I enter the number of copies for example the value 5.
The total amount is 0.50 euros but I have like message:
I don't understand how to declare the variable total correctly in double.
H
D NumberCopy S 3S 0
D Total S ???
*
/Free
dsply 'Enter your copy number please : ' '' NumberCopy;
If (NumberCopy < 11);
Total = NumberCopy * 0.10;
ElseIf (NumberCopy < 31);
Total = (10 * 0.10) + (NumberCopy - 10) * 0.09;
Else;
Total = (10 * 0.10) + (20 * 0.09) + (NumberCopy - 30) * 0.08;
EndIf;
dsply ('The amount is of ' + %Char(Total) + ' euros');
*inlr = *on;
/End-Free
Here I find this on RPGPDM.
D Float1 S 8F
https://www.rpgpgm.com/2014/02/defining-variables-in-rpg-all-free.html
You have declared Float1 as a "double". But the problem is that floating point numbers are not a good choice for fixed decimal precision numbers. See https://en.wikipedia.org/wiki/Floating-point_arithmetic#Accuracy_problems .
You should use packed or zoned if you are working with numbers where correct precision is needed and not just some approximation.
to say it at the beginning of your exercise DONT USE FLOAT IN RPG. It will make you pretty unhappy. To answer your question: dcl-s total float(8); You have two problems with float:
You dont want your customers to get wrong invoices due to accuracy problems like in 1990.
Decimals are able too use hardware support to evaluate faster which isn't "important" but a nice to have.
If you wanna display a float you can do something like that
dcl-s outputString char(10) inz;
dcl-s total float(8) inz (5);
outputString = %char(%dec(total: 10: 2));
dsply outputString;
Some hints:
Don't use /free or /end-free the compiler is able to acknowledge tht on its own.
Don't use fixed format declarations to define your fields. They are harder to read and there is no actual reason to use them.

how to limit the number of digit after the float with python 3?

In my program I have several calculations that produce float numbers as results.
I would like to know if there's a general declaration in Python 3 that allows to limit all the floats in the program to let's say 8 digits, systematically ?
Thank you for your help !
# Create initial balance for user 1 and user 2.
bal_user1 = 21.82233503
bal_user2 = 5.27438039
# Calculate percentage of capital for each user
percent_capi_user2 = 100 * bal_user2 / ( bal_user1 + bal_user2)
percent_capi_user1 = 100 - percent_capi_user2
print("User 1 as " + str(percent_capi_user1) + (" % of the capital"))
print("User 2 as " + str(percent_capi_user2) + (" % of the capital"))
The output is :
User 1 as 80.53498253110413 % of the capital
User 2 as 19.465017468895866 % of the capital
I would like for example : 80.53498253 instead of 80.53498253110413
And since I'm doing several calculations later on in the program, I was wondering if there was a general declaration to put once at the beginning of the code. In order to avoid casting the right number of digits each time...
Well, buddy, I think I have just what you are looking for!
What you are looking for is the decimal module and the included Decimal class. Now, I am not going to go into it, because I am not that knowledgeful in it, but what I can do is point you in the right direction. In short, read the documentation here ( https://docs.python.org/3/library/decimal.html?highlight=decimal#module-decimal ), and look for decimal.getcontext().prec, which will allow you to, at least with Decimal objects, control their precision "globally".

Difference in Macro vs Manual Output on same formula using LOG

Well its rather a very strange question
I have a macro which generates the delta of a Option(d1):
Function dOne(UnderlyingPrice, ExercisePrice, Time, Interest, Volatility, Dividend)
dOne = (Log(UnderlyingPrice / ExercisePrice) + (Interest - Dividend + (0.5 * Volatility ^ 2)) * Time) / (Volatility * (Sqr(Time)))
End Function
When I pass the the values to it, it generates the desired output:
However when I try to replicate this in Excel, it gives an entirely different output
I know that the calculations for output generated manually are correct.
However the desired values are those generated from VBA.
Please suggest what am I missing here.
The Log function in VBA is the natural log: ln(x).
The LOG function in the formula is log base 10: log10(x).
If you want log base 10 in VBA you will have to use the logarithmic identity for converting bases:
Log(x)/Log(10)
In your case
dOne = (Log(UnderlyingPrice / ExercisePrice) / Log(10) + (Interest - Dividend + (0.5 * Volatility ^ 2)) * Time) / (Volatility * (Sqr(Time)))

how to use decimal values in Math.pow()

I have a calculation:
(22,582 / 10,000)^1/15 - 1
In C# I am using like this:
double i = Math.Pow(2.2582,1/15) - 1;
Response.Write(i);
But everytime it returns me 0 in i. I know (1/15) is making some disturbance in the calculation, so to solve this I used (.067) in place of (1/15) which gives me result 0.0560927980835855, but I am still far away from my actual result. Can somebody please tell the right approach.
The first calculation should be:
(22.582d / 10.000d) * (1.0d/15.0d) - 1.0d
You use the "d" in literals to tell the compiler that the number should be a double. If you don't use it the compiler thinks that 1/15 is two integers divided resulting in 0.
So the last calculation should be:
double i = Math.Pow(2.2582d, 1.0d/15.0d) - 1.0d;
Response.Write(i);
This means that:
1/15 = 0
and
1.0d/15.0d = 0.06666667
Here 1 and 15 are considered as integers and were calculated to find the integer result 1/15 =0;
not the double result.
Try using 1f/15f instead of 1/15

Resources