Rounding arithmetic in accounting - math

Note
This is for an accounting software, so the values are rounded to cents (2 decimal places).
Question
Given the final value invoice value of $4488.70 (we can call this value final), obtain the initial subtotal value (subtotal) in such a way that:
subtotal + round(0.07 * subtotal) - round(0.02 * subtotal) = final
For the case of final being $4488.70,
by directly doing division by 1.02 and obtaining $4400.6862745 (rounded to $4400.69)
For an invoice, this wouldn't tally because:
Subtotal 4400.69
VAT (7%) 308.05 ==> round(4400.69 * 0.07)
WHT (5%) 220.03 ==> round(4400.69 * 0.05)
==========
Final 4488.71 (4400.69 + 308.05 - 220.03)
That is not the wanted final value (off by 1 cent).
The better subtotal here should instead be 4400.68, but how do we obtain that algorithmically?
Subtotal 4400.68
VAT (7%) 308.05 ==> round(4400.68 * 0.07)
WHT (5%) 220.03 ==> round(4400.68 * 0.05)
==========
Final 4488.70 (4400.68 + 308.05 - 220.03)
Current proposed solution
Internally we are proposing doing a 3 passes by firstly obtain tentative subtotal = final/1.02, and work forward to see if we get the final intended value, if not, we try subtotal - 1 and ultimately subtotal + 1.
Pass 1: final/1.02
Pass 2: final/1.02 - 0.01
Pass 3: final/1.02 + 0.01
Is there a better, more efficient and still as reliable method as the proposed one?

What you want is not achievable in general. There might be some value final for which no such subtotal exists. (I'm too lazy to do a mathematical proof now, but I'm sure that some value can be found for which subtotal yields desiredFinal - 0.01 and subtotal + 0.01 yields desiredFinal + 0.01 due to the way rounding is performed).
There are two common ways to solve this:
subtotal = final/1.02, then calculate everything else, like you did in your first example:
Subtotal 4400.69
VAT (7%) 308.05 ==> round(4400.69 * 0.07)
WHT (5%) 220.03 ==> round(4400.69 * 0.05)
==========
Final 4488.71 (4400.69 + 308.05 - 220.03)
If there is a cent difference, add or remove it from subtotal and final. That means that VAT and WHT won't be precise w.r.t. subtotal.
Subtotal 4400.68 ==> one cent removed
VAT (7%) 308.05
WHT (5%) 220.03
==========
Final 4488.70 ==> one cent removed
Explicitly mention the rounding error:
Subtotal 4400.69
VAT (7%) 308.05
WHT (5%) 220.03
Rounding - 0.01
==========
Final 4488.70
Which one to choose depends on your local tax legislation.

Related

Multiplication by %s when language dictates division rounds down by default

In erlang:
cost(I, Miners) ->
BasePrice = lists:nth(I, prices()),
Owned = lists:nth(I, Miners),
Rate = increaseRate(I) / 100,
Multiplier = math:pow((1 + Rate), Owned),
floor(BasePrice * Multiplier).
for example, a base price of 8000, with an increase rate of 7, and I own 0
the price of the first one I expect to be: 8000
when buying my second one, with an increase rate of 7, and I own 1
the price of the second one I expect to be:
Multiplier = 1.07
8000 * 1.07 =
8560
This all works fine. Now I have to implement this in Solidity, which doesn't do decimal math very well. It auto rounds down such that 3/2 == 1 in Solidity.
I want to recreate my cost function in Solidity.
function cost(uint _minerIndex, uint _owned) public view returns (uint) {
uint basePrice = 8000;
uint increaseRate = 7;
return basePrice * ((1 + increaseRate / 100) ** _owned);
}
increaseRate / 100 will always return 0 if increaseRate is < 100.
How do I achieve this same effect?
From the documentation:
"Fixed point numbers are not fully supported by Solidity yet. They can be declared, but cannot be assigned to or from."
a simple solution is
(basePrice * ((100+increaseRate)** _owned))/(100 ** _owned)
but it may fail also because of arithmetic overflow, depending on your numbers and the MaxInt supported by solidity.

Estimate maximum relative error of concatenated floating-point operations

According to this very elaborate answer I would estimate the maximum relative error δres,max of the following computation like this:
// Pseudo code
float a, b, c; // Prefilled IEEE 754 floats with double precision
res = a / b * c;
res = a * (1 + δa) / ( b * (1 + δb) ) * (1 + δa/b) * c * (1 + δc) * (1 + δa/b*c)
= a / b * c * (1 + δa) / (1 + δb) * (1 + δa/b) * (1 + δc) * (1 + δa/b*c)
= a / b * c * (1 + δres)
=> δres = (1 + δa) / (1 + δb) * (1 + δa/b) * (1 + δc) * (1 + δa/b*c) - 1
All δs are within the bounds of ± ε / 2, where ε is 2^-52.
=> δres,max = (1 + ε / 2)^4 / (1 - ε / 2) - 1 ≈ 2.5 * ε
Is this a valid approach for error estimation that can be used for every combination of basic floating-point operations?
PS:
Yes, I read "What Every Computer Scientist Should Know About Floating-Point Arithmetic". ;)
Well, it's probably a valid approach. I'm not sure how you've jockeyed that last line, but your conclusion is basically correct (though note that, since the theoretical error can exceed 2.5e, in practice the error bound is 3e).
And yes, this is a valid approach which will work for any floating-point expression of this form. However, the results won't always be as clean. Once you have addition/subtraction in the mix, rather than just multiplication and division, you won't usually be able to cleanly separate the exact expression from an error multiplier. Instead, you'll see input terms and error terms getting multiplied directly together, rather than the pleasantly relatively constant bound here.
As a useful example, try deriving the maximum relative error for (a+b)-a (assuming a and b are exact).

Circular DHT with different implementations

I had the following question in my exam:
This problem involves a circular DHT in which every peer node tracks just its predecessor and the successor. No shortcuts are available.
Consider the following three constructions below. In all these three construction, the node IDs range
from 0 to N − 1 and so do the key IDs. At a given time, the number of peer nodes participating in
the DHT is M and this number is readily known to all peer nodes. The ‘value’ in the (key, value)
pair is the set of IDs of the nodes that independently store the data of interest.
C-1: Every stored (key, value) pair (k, v) is stored at a random node (from among the ones that are online then).
C-2: Every stored (key, value) pair (k, v) is stored at a node whose ID is given by k mod M.
C-3: Every stored (key, value) pair (k, v) is stored at a node whose ID is k (if it is online) or its closest online successor (with wraparound).
(a) An online peer wants to find out a key k to get the corresponding value. What is the
complexity (i.e., the big-oh O( )) of this operation in each of the three constructions. If you are
not familiar with the O( ) notation, just state the average number of queries launched.
(b) An online node launches a query for key k and gets a set of two node IDs in return.
What are the chances at least one of those nodes is online (such that the querying node can get
the data of interest)? Provide your answer for each construction; your answer may be in terms of
k, M, N, or any other parameter.
(c) What would be your (numerical) answer to above part (for each construction) if on
average 30% nodes are online.
I have confusion over the answers I wrote. I want to know whether what I did is correct or not.
I wrote the following answers :
a) C1: O(N) - in the case there are N nodes online
C2: O(M) - in the case the keys are from 0 to M-1
C3: O(1) - worst case node with key k is offline the next one is looked at
b) p=probability of being online
C1: 2C1 * p * (1-p) + 2C2 * p
C2: 2C1 * p * (1-p) + 2C2 * p
C3: 2C1 * p * (1-p) + 2C2 * p
c) C1 : 2C1 * 0.3 * 0.7 + 2C2 * 0.3
C2 : 2C1 * 0.3 * 0.7 + 2C2 * 0.3
C3 : 2C1 * 0.3 * 0.7 + 2C2 * 0.3
a) For C1 you have stated the answer for the case when M = N, this may not always hold so you should change it to O(M) since it will search all the online nodes as any one of them can hold the key at random.
C2: O(M) is correct as well as the reason you stated.
C3: this too will be O(M), as on average you are going to have to traverse the whole DHT to find the key.
b)
You have used the wrong formula for the binomial theorem.
The correct formula is:
nCk * p^k * (1-p) ^ (n-k)
So your answers should be:
C1: 2C1 * p * (1-p) + 2C2 * p^2
C2: 2C1 * p * (1-p) + 2C2 * p^2
C3: 2C1 * p * (1-p) + 2C2 * p^2
Also, note that here p = M/N (since M nodes online from N nodes)
c)
Now p = 0.3
C1 : 2C1 * 0.3 * 0.7 + 2C2 * 0.3^2 = 0.51
C2 : 2C1 * 0.3 * 0.7 + 2C2 * 0.3^2 = 0.51
C3 : 2C1 * 0.3 * 0.7 + 2C2 * 0.3^2 = 0.51

Need help wit heartrate calculation for watch

So I'm trying to animate a fake heartbeat for my Android wear watchface. I have an API that grabs the heartrate in BPM and the current millisecond now I'm trying to use an equation to make an image "beat" to the BPM. Here's the psuedocode:
IF (Millis / HeartRate) % (1000 / HeartRate) <= 1)
Opacity = 100;
ELSE
Opacity = 75;
ENDIF
I'm really not sure if I calculated it properly. I don't think the image is properly flashing at the correct rate. Any help with the math would be appreciatred!
A value in BPM is a frequency, rather than a period of time:
b BPM = b / 60s = b/60 * s^-1
The period of the oscillation is
T = 1/f = 60s / b = 60/b s
If we have a time in milliseconds, then we can work out the modulo vs the period:
remainderInSeconds = CurrentTimeInSeconds % T
= (CurrentTimeInMilliseconds * 1e-3) % T
= (CurrentTimeInMilliseconds * 1e-3) % (60/BeatsPerMinute)
fraction = remainderInSeconds / Period
= [(CurrentTimeInMilliseconds * 1e-3) % T] / T
= (CurrentTimeInMilliseconds * 1e-3 / T) % 1
= (CurrentTimeInMilliseconds * 1e-3 / (60/BeatsPerMinute)) % 1
= (CurrentTimeInMilliseconds * 1e-3 * BeatsPerMinute / 60)) % 1
= (CurrentTimeInMilliseconds * BeatsPerMinute / 60e3)) % 1
Then you can check whether the fraction is below your threshold; if you want the pulse to last a 20th of the period, then check if fraction < 1/20.
Alternatively just calculate the remainder in seconds, if you want the pulse to last a specific amount of time rather than a portion of the period.
I managed to compile a new code using a different variable from the watch API. This other variable is essentially a number between 0 and 359 which steps up at mere decimals per frame. (The variable is normally used for a smooth motion second hand).
I also decided to use a sine wave and RGB shaders instead of opacity. Here is the new code
Green = 0
Blue = 0
Red = 100 * math.sin(HeartRate * SecondsRotationSmooth / 60)
Using this particular variable isn't ideal, but it at least gives me a better looking code. If anyone wants to give a better answer please do!

Getting confused why i dont get expected amount?

I have 1 result and which i will receive in Bank account, Based on that account i have to Put a balance to user account.
How can you find the Handling cost from total tried 491.50 / 0.95 = 517.36 which is wrong ? It should be 500.00 (to my expectation)
User balance requires 500.00
When 500.00 selected he gets 5% discount
There is a handling cost for this
ex:
1) Discount: 500.00 - 5% = 475.00
2) Handling cost: (475.00 x 0.034) + 0.35 = 16.50
3) Total: 475.00 + 16.50 = 491.50
So problem is from 491.50, i have to find atleast handling cost to get promised Balance.
Any solution ? Cant figure it out myself...
In short cut:
a) i put 491.50 -> b) my formula will suggest me apply balance 500.00 (which is the main goal)
So, your maths can be represented as:
((0.95 * initialCost * 0.034) + 0.35) + (0.95 * initialCost ) = finalCost
which reduces to
(0.9823 * initialCost) + 0.35 = finalCost
It follows that
initialCost = (finalCost - 0.35) / 0.9823
(final_price - 0.35) / 1.034 / 0.95
For 491.50, this yields 500.
You might try to combine the last 2 divisions to be divide by 1.034 * 0.95 = 0.9823, but you will have to guard against rounding errors due to using floating point arithmetic.

Resources