Calculate amount of $ before fees - PHP - php

I'm trying to make a small calculator, as a personal project. I have a little example here, what I want:
The user(me) get paid 10$ from a customer. What I do, is first to subtract the percentage which is 2.75% so after the subtraction I will have 9.725$ back. Then I take 1.5$ in fee. So I will be down on 8.225$ in the end.
That one works as it should.
What I then want to calculate is.
If I want 10$ AFTER fees are paid, (the 2.75% and 1.5$), how much should the customer then pay? and how could I do the calculation, so I could use any amount of moneys I want to receive.
Hope any can solve this 'easy' math problem.
A little bonus I would like to do also, is, if I edit the percentage to 3% etc, it should work too. (If impossible, then never mind).
I'm feeling really lost here at the moment!
Here are what I currently do, but it just adds 2.75% and the 1.5$ to the amount I specified.
function retPercent($amount, $percent)
{
return $amount + ($amount / 100 * $percent);
}
The problem here, is that I still don't know how to calculate the percentage I actually should use (based on the 2.75%) that I get from the substraction.
Thank you a lot guys and girls!

$result = ($value + 1.5) / 0.9725;
Or more generally:
function myFunc($value, $percentage, $fee) {
return ($value + $fee) / ((100-$percentage) / 100);
}
Other way round:
function myFuncTwo($result, $percentage, $fee) {
return (((100-$percentage) / 100) * $result) - $fee;
}
Example Use:
echo myFunc('8.225', '2.75', '1.5'); //10
echo myFuncTwo('10', '2.75', '1.5'); //8.225

Related

What is the best way to move decimal point in PHP

I'm working on project where you can make payments with credit card.
I have booking system from what I get "price" and then it sends this price to merchant online payment page.
My problem is that booking system sends price in decimal. Like 123.45.
But merchant accepts only this format: 12345. And after receiving this format it ads decimal point automatically.
I need to convert this "price" without decimal point. In other words move it to right. What is the best function or solution to do that?
For now I'm using round() function and add two zeros (00). But this way is only if I really use rounded up prices.
$price = $_POST['price'];
$price = round($price) . '00';
I expect the output 123.45 to be 12345. Other example 123.00 to be 12300.
Careful... you may lose precision. I had to switch to using bcmul()
$version=22.0220;
$int1=(int)($version*10000); // $int1 is 220219 (oops)
$int2=(int)(bcmul($version,10000)); // $int2 is 220220 (correct)
<?php
$withoutDecimal = $withDecimal * 100;
?>
For those who need more flexible solution. For example, Bitcoin has 8 decimal places, US dollar - 2
function price_minor_units($dollars, $decimals = 2)
{
return $dollars * (10 ** $decimals);
}
function price_major_units($cents, $decimals = 2){
return $cents / (10 ** $decimals);
}

PHP calculation logic issue

Not sure if I'm being stupid here. Probably something obvious but when you've been staring at the same issue for hours on end it starts to drive you crazy.
I'm doing a few calcuations using PHP, all fairly straight forward.
I have a table called sales, say:
total, costs
424.53, 125
853.91, 125
To get the data I need...
gross = total - cost
vat = gross - ( gross / 1.2 )
profit = gross - vat
I need to generate a report, so for each row in the sales database I need to loop over and run the above calculations to get the data I need.
If I add the sum of total and the sum of costs, and then work out the gross, vat and profit above, and round vat and profit to 2 decimal plates the values are as expected.
The problem I'm having is where I'm looping over each row and calculating gross, vat and profit. If I don't round vat and profit on each row, but round the final totals, they match the values where I add sum(total) and sum(costs).
But then in the report I generate, if I don't round vat and profit then they don't show to two decimal places, which I need.
Actual code is below, pretty sure it's more of a logic issue than code.
$sum = 0; // Test variable
foreach( .. as ... )
{
// Assigning $total and $cost
$gross = $total - $cost;
$data['profit'] = $gross;
// If I round this VAT so vat shows to two decimal points, $sum becomes off by some pence.
// If I don't round it but then round $sum after the loop, it matches the echo statement value which is the correct amount
$vat = $this->vat( $gross );
$data['vat'] = $vat;
$profit = $gross - $vat;
$data['net_profit'] = $profit;
$sum += $profit;
$array[] = $data;
}
echo "131547.82<br><br>";
echo $sum;
die;
It's an accuracy problem caused by using floats.
When you do calculations with pure PHP you need to be careful.
You may run into glitches, when comparing two floats.
I would suggest to use some helper function or a currency / money object in order to work with them. It might be better to use a PHP Extension for math stuff, like the PHP Extensions BCMath, which has for instance the function bcadd(). Anyway, here are some helpers, which you might use in your calculation loop.
/**
* turn "string float" into "rounded float with precision 2"
* (string) 123,19124124 = (float) 123.19
*
* #param type $string
*/
function formatNumber($string, $precision = 2)
{
return round((float) str_replace(',', '.', $string), $precision);
}
There is also sprintf: echo sprintf("%.2f", $a);.
These two are based on PHP's NumberFormatter from the Intl Extension.
// 123,19 EUR = 123.19
function parseNumber($string_number)
{
$fmt = numfmt_create('de_DE', \NumberFormatter::DECIMAL);
return numfmt_parse($fmt, $string_number);
}
// 123.19 = 123,19 EUR
function numberFormat($value)
{
$f = \NumberFormatter::create("de_DE", \NumberFormatter::CURRENCY);
return $f->formatCurrency($value, 'EUR');
}
For comparing two floats:
/**
* Do not check, that the numbers are exactly the same,
* but check that their difference is very small!
* A really small rounding error margin (epsilon) is expected.
* It's an equals check within defined precision.
*/
function compareFloats($a, $b)
{
return (abs(($a - $b) / $b) < 0.000001) ? true : false;
}

understanding phpexcel RATE function

The Formula call for variables. I've look all over and can't find what these variables are and what values they're supposed to represent.
RATE($nper, $pmt, $pv, $fv = 0.0, $type = 0, $guess = 0.1)
Is anyone familiar with this function? Do you know what values the variables are meant to represent?
From the Excel help file:
RATE(nper,pmt,pv,fv,type,guess)
For a complete description of the arguments nper, pmt, pv, fv, and
type, see PV.
Nper - is the total number of payment periods in an annuity.
Pmt - is the payment made each period and cannot change over the life of the annuity. Typically, pmt includes principal and interest
but no other fees or taxes. If pmt is omitted, you must include the fv
argument.
Pv - is the present value — the total amount that a series of future payments is worth now.
Fv - is the future value, or a cash balance you want to attain after the last payment is made. If fv is omitted, it is assumed to be 0 (the
future value of a loan, for example, is 0).
Type - is the number 0 or 1 and indicates when payments are due.
Set type equal to the following if payments are due:
0 or omitted - At the end of the period
1 - At the beginning of the period
Guess - is your guess for what the rate will be.
If you omit guess, it is assumed to be 10 percent.
If RATE does not converge, try different values for guess. RATE usually converges if guess is between 0 and 1.
Remark
Make sure that you are consistent about the units you use for
specifying guess and nper. If you make monthly payments on a four-year
loan at 12 percent annual interest, use 12%/12 for guess and 4*12 for
nper. If you make annual payments on the same loan, use 12% for guess
and 4 for nper
I dont know if you need to implement this function, but in any case, I looked at how this algorithm was built and even though I was not able to access the excel source code (or the google worksheet) I found that this is not a simple calculation. About this math, more can be read here:
https://brownmath.com/bsci/loan.htm#Eq8
The function, in PHP, may be something like this:
function rate($nprest, $vlrparc, $vp, $guess = 0.25) {
$maxit = 100;
$precision = 14;
$guess = round($guess,$precision);
for ($i=0 ; $i<$maxit ; $i++) {
$divdnd = $vlrparc - ( $vlrparc * (pow(1 + $guess , -$nprest)) ) - ($vp * $guess);
$divisor = $nprest * $vlrparc * pow(1 + $guess , (-$nprest - 1)) - $vp;
$newguess = $guess - ( $divdnd / $divisor );
$newguess = round($newguess, $precision);
if ($newguess == $guess) {
return $newguess;
} else {
$guess = $newguess;
}
}
return null;
}

Point Formula based on a dynamic amount

I'm trying to create a dynamic point system based off of how much money is available in a bank account. For instance, if someone has 20 points and we have 100 dollars in the bank account, I want the formula to return something along the lines of $1.
I don't care too much about the ratio at this point - more about the formula to get there.
So far, I've come up with a handful of different formulas,
$val = (1 / $this->bank) * $amt; //goes the wrong way
$val = ($amt / $this->bank) * 5000; //isn't a good ratio
Assume val is the amount you can get with all the points, bank is how much is in the bank, and $amt is the amount of points the user has.
A gentle nudge in the right direction would be helpful!
Thanks!
$bank * ($points / 2000)
This satisfies your test case, giving 1 for $bank = 100 and $points = 20.
Saying $percentage is the percentage you want between your points and the bank account amount to have 1$ reward, you will have:
$percentage = 20;
$val = $amt * $this->bank / ($percentage * 100);

Generate a fictitious stock option price variation

What I do
I am making graph of fictitious stock options.
The price is updated each second, with this function
function stockVariation($price,$max_up,$max_down)
{
// Price > 1
if($price > 1)
{
// Calculate
$ratio=(mt_rand(0,$max_up/2)-mt_rand(0,$max_down/2))/1000;
$price+=$ratio;
}
// Price <=1 (we don't want 0 or negative price...)
else
$price+=mt_rand(1,$max_up)/1000;
return round($price,3);
}
I use a max_up and max_down values (from 10 to 100) to make the price change progressively and simulate some volatility.
For example, with max_up : 40 and max_down : 45, the price will progressively go down.
My question
But the problem, is that prices generated are too much volatile, even if max_up = max_down.
The result is "non-natural". (for example +10 points in one day for a base price of 15,000).
Result of price evolution per hour in 24 hour
Perhaps making round($price,4) and divisions by 10 000 instead of 1 000, will be better ?
If anyone have an idea or an advice to generate "natural" prices evolution, thanks in advance.
There are 86400 seconds in a day, so you'll need to divide by a much larger number. And rather than adding and subtracting, you may want to multiply the current price by a factor that's slightly larger or smaller than 1. That would simulate a percentage increase or decrease, rather than an absolute gain or loss.
function stockVariation($price, $max_up, $max_down)
{
// Convert up/down to fractions of the current price.
// These will be very small positive numbers.
$random_up = mt_rand(0, $max_up) / $price;
$random_down = mt_rand(0, $max_down) / $price;
// Increase the price based on $max_up and decrease based on $max_down.
// This calculates the daily change that would result, which is slightly
// larger or smaller than 1.
$daily_change = (1 + $random_up) / (1 + $random_down);
// Since we're calling this function every second, we need to convert
// from change-per-day to change-per-second. This will make only a
// tiny change to $price.
$price = $price * $daily_change / 86400;
return round($price, 3);
}
Building upon the idea, you could use an actual volatility number. If you want e.g. a volatility of 35%/year, you can find the volatility per second. In pseudocode:
vol_yr = 0.35
vol_month = vol_yr * sqrt(1.0/12)
vol_second = vol_yr * sqrt(1.0/(252 * 86400)) # or 365 * 86400
Then, every second, you "flip a coin" and either multiply or divide current stock price by (1 + vol_second). This is the principle of how binomial trees are created to evaluate exotic stock options.

Categories