Setting a new variable in each multiple of 10, with no limit - php

i'm hoping someone can help with my question.
Let's say I have a quantity which is simply an integer in a variable. I know that if the quantity is below 10, the cost will be 1.50. Between 10-20 the cost would be 1.50 x 2, then between 20-30 the cost would be 1.50 x 3 and so on.
The bit im stuck on is the "and so on". I know how I could code this if I knew there was a limit of let's say 100, however if it can be limitless, how could I code this in an intelligent way to work it out for me?
Sorry for the example-less question. I wouldn't know where to start with this query.
Thank you for your time

Since your steps are in tenfold, you can simply divide your number by 10 to get the amount of 1.5's you'll need to calculate the cost.
Then, we'll use ceil() to round the divison to the next integer. Now, for example, 5/10 = 0,5 results in return 1.5 * 1;
Take a look at this example;
<?php
function getCost($n) {
return 1.5 * ceil($n / 10);
}
var_dump(getCost(5)); float(1.5)
var_dump(getCost(15)); float(3)
var_dump(getCost(25)); float(4.5)
var_dump(getCost(35)); float(6)
var_dump(getCost(100)); float(15)
var_dump(getCost(12345)); float(1852.5)
Try it online!

Related

round decimals to a specific value with php

I am trying to make a float number e.g. 110.34 to "round" to 110.90
The thing is I am converting product prices caused by currency switcher and I want to make the values values look good.
I have somewhere the function
function($price)
which gives me the price of the product.
And I was trying to make it with the round() function e.g.
return round($price * 2, 0) / 2;
But this will round it to x.00 or x.50
Is there any other function that can round all values to x.90?
Now i made it like this?
return intval($price) + 0.90;
is this the right way, at least it looks good. :-D

What is the correct format to use in PHP when denoting "money" attribute fetched from MySQL database?

I'm using the "number_format" function to denote money" attribute in PHP/MySQL.
The attribute itself is stored in my database.
Select account_balance from my_table where login = 'xxxxxx';
$correct_account_balance = number_format($account_balance,
['my_balance'],2); }
In other words : the denotation "2" will add two extra numbers after the decimal point, as follows : 10.00 (for example)
This code works fine............except for one small problem : if the amount after the decimal point has a zero at the end, it does not display!
For example : if the amount is, say, 10 dollars and 35 cents, it displays correctly : 10.35
However, if the amount is 10 dollars, and 30 cents, it displays as : 10.3 (instead of : 10.30 )
The reason is : my program also performs arithmetical operations on the account_balance AFTER I have converted it using the "number_format" function.
For example :
$correct_account_balance -= 0.25 (this will subtract 0.25 each time the program is executed)
This is why, anytime there is a "zero" at the end of the actual amount (like : 10.30), it displays as : 10.3
Is there anyway to get around this? Google doesn't seem to know;
The reason is : my program also performs arithmetical operations on the account_balance AFTER I have converted it using the "number_format" function.
You'll need to re-run number_format after doing the operations on it.
You really shouldn't run it at all until it's ready for display, either, the commas it adds to larger numbers will hugely mess up your calculations. As an example, the following:
<?php
$number = 100000.30;
$number = number_format($number, 2);
$number -= 0.25;
echo number_format($number, 2);
results in the output:
99.75
Which means you've just stolen $99,900.55 from your customers with a type conversion error.

Using round() to get exact value - PHP

Hey guy's I am working on a project of mine which involves the use of money. I am trying to not use round anymore because, it's rounding things to nearest tenth and I need exact numbers. One reason I was using it, was because it was giving a whole number.
The way I am working my number system is that 100 = $1, 2000 = $20, etc.. I was currently using the round function because it would get rid of the decimal point for me and give me a whole number, lets say: 223 which in turn would = $2.23.
Here is what I am using:
$amount += round(($amount / 29) + 30);
Here are the numbers:
Lets say we have a charge of 100 and we add 125 which equal 225 (USD $2.25). Now we add taxes and processing: + 2.9% + $.30. After multiplying 2.25 by 2.9% and adding .30 the amount would be: 0.36525 - this is the amount that should be added than to the $2.25 which than would be 261 = $2.61
The issue is because of the rounding, when I look in my Stripe panel (I am using Stripe API for payments) I see a charge of $2.63. So my question is, how would I go about making it exact without having any rounding and decimal places.
UPDATE:
Here is the above example more explained:
Lets say we have a charge of 100 and we add 125 which equal 225 (USD $2.25). Now we add taxes and processing: + 2.9% + $.30. After multiplying 2.25 by 2.9% and adding .30 the amount would be: 0.36525 - this is the amount that should be added than to the $2.25 which than would be 261 = $2.61
So now with that the actual value of amount that should be charged is $2.61 but instead when using the round it gives me 263 which also means $2.63. The above example is the simple math that is correct.
In order to avoid calculation hiccups like that, only round the final result. Keep all other calculations as accurate as possible:
$original = 100;
$original += 125;
$tax = $original * 2.9 / 100; //+2.9%
$tax += 30; //+$.30
$original += $tax; //Add tax.
echo $original; //Result is 261.525. Round as you please.
You can specify precision and rounding method to keep it consistent (PHP round()), then you can deal with the actual values. Doing math tricks like multiplication by a multiple of 10 will only make it more confusing in the long run.
$amount += round(($amount / 29) + 30, 2, PHP_ROUND_HALF_UP);
Will this solve your problem?

PHP - get closest number given a certain number?

I'm modifying one of OpenCart's product filters to filter products in/out by price. What I do is get all products belonging to a certain category and extract their prices to put them in a slider, but this is not elegant or 'professional' at all, and I would like to code a proper solution.
Let's say I have the following prices: 125, 270, 517, 1680 and 14790. What I would like to do (ideally) is get the highest number (14790 in this short example) and, from it, get something like '15000', so I can divide that between a given factor (like 100) and put that into a slider.
Is there a PHP function to do this kind of calculation?
If I understand your question, and you're asking to round to essentially the nearest 100, there isn't a specific function, but with a bit of maths you can round to the nearest hundred like so:
$price = ceil($price / 100) * 100;
Using:
$price = ceil($price / 1000) * 1000;
Would round to the nearest 1000.
Get the max number, then round it up to the nearest thousand?
<?php
$largest = max(125, 270, 517, 1680, 14790);
$nearest = ceil($largest / 1000) * 1000;
You could just loop through the numbers, remembering the highest value as you go. It's common coding practice. (Ok there really is a max() function as well, echo max(1, 3, 5, 6, 7); // 7)
Then you could divide the highest number by your factor, take the integer you get and add one to it, then multiply by the factor again and there you go.
just do : x=floor(14790/100) ; the floor function returns the next lowest integer value

How can I create a specified amount of random values that all equal up to a specified number in PHP?

For example, say I enter '10' for the amount of values, and '10000' as a total amount.
The script would need to randomize 10 different numbers that all equal up to 10000. No more, no less.
But it needs to be dynamic, as well. As in, sometimes I might enter '5' or '6' or even '99' for the amount of values, and any number (up to a billion or even higher) as the total amount.
How would I go about doing this?
EDIT: I should also mention that all numbers need to be a positive integer
The correct answer here is unbelievably simple.
Just imagine a white line, let's say 1000 units long.
You want to divide the line in to ten parts, using red marks.
VERY SIMPLY, CHOOSE NINE RANDOM NUMBERS and put a red paint mark at each of those points.
It's just that simple. You're done!
Thus, the algorithm is:
(1) pick nine random numbers between 0 and 1000
(2) put the nine numbers, a zero, and a 1000, in an array
(3) sort the array
(4) using subtraction get the ten "distances" between array values
You're done.
(Obviously if you want to have no zeros in your final set, in part (1) simply rechoose another random number if you get a collision.)
Ideally as programmers, we can "see" visual algorithms like this in our heads -- try to think visually whatever we do!
Footnote - for any non-programmers reading this, just to be clear pls note that this is like "the first thing you ever learn when studying computer science!" i.e. I do not get any credit for this, I just typed in the answer since I stumbled on the page. No kudos to me!
Just for the record another common approach (depending on the desired outcome, whether you're dealing with real or whole numbers, and other constraints) is also very "ah hah!" elegant. All you do is this: get 10 random numbers. Add them up. Remarkably simply, just: multiply or divide them all by some number, so that, the total is the desired total! It's that easy!
maybe something like this:
set max amount remaining to the target number
loop for 1 to the number of values you want - 1
get a random number from 0 to the max amount remaining
set new max amount remaining to old max amount remaining minus the current random number
repeat loop
you will end up with a 'remainder' so the last number is determined by whatever is left over to make up the original total.
Generate 10 random numbers till 10000 .
Sort them from big to small : g0 to g9
g0 = 10000 - r0
g1 = r0 - r1
...
g8 = r8 - r9
g9 = r9
This will yield 10 random numbers over the full range which add up to 10000.
I believe the answer provided by #JoeBlow is largely correct, but only if the 'randomness' desired requires uniform distribution. In a comment on that answer, #Artefacto said this:
It may be simple but it does not generate uniformly distributed numbers...
Itis biased in favor of numbers of size 1000/10 (for a sum of 1000 and 10 numbers).
This begs the question which was mentioned previously regarding the desired distribution of these numbers. JoeBlow's method does ensure a that element 1 has the same chance at being number x as element 2, which means that it must be biased towards numbers of size Max/n. Whether the OP wanted a more likely shot at a single element approaching Max or wanted a uniform distribution was not made clear in the question. [Apologies - I am not sure from a terminology perspective whether that makes a 'uniform distribution', so I refer to it in layman's terms only]
In all, it is incorrect to say that a 'random' list of elements is necessarily uniformly distributed. The missing element, as stated in other comments above, is the desired distribution.
To demonstrate this, I propose the following solution, which contains sequential random numbers of a random distribution pattern. Such a solution would be useful if the first element should have an equal chance at any number between 0-N, with each subsequent number having an equal chance at any number between 0-[Remaining Total]:
[Pseudo code]:
Create Array of size N
Create Integer of size Max
Loop through each element of N Except the last one
N(i) = RandomBetween (0, Max)
Max = Max - N(i)
End Loop
N(N) = Max
It may be necessary to take these elements and randomize their order after they have been created, depending on how they will be used [otherwise, the average size of each element decreases with each iteration].
Update: #Joe Blow has the perfect answer. My answer has the special feature of generating chunks of approximately the same size (or at least a difference no bigger than (10000 / 10)), leaving it in place for that reason.
The easiest and fastest approach that comes to my mind is:
Divide 10000 by 10 and store the values in an array. (10 times the value 10000)
Walk through every one of the 10 elements in a for loop.
From each element, subtract a random number between (10000 / 10).
Add that number to the following element.
This will give you a number of random values that, when added, will result in the end value (ignoring floating point issues).
Should be half-way easy to implement.
You'll reach PHP's maximum integer limit at some point, though. Not sure how far this can be used for values towards a billion and beyond.
Related: http://www.mathworks.cn/matlabcentral/newsreader/view_thread/141395
See this MATLAB package. It is accompanied with a file with the theory behind the implementation.
This function generates random, uniformly distributed vectors, x = [x1,x2,x3,...,xn]', which have a specified sum s, and for which we have a <= xi <= b, for specified values a and b. It is helpful to regard such vectors as points belonging to n-dimensional Euclidean space and lying in an n-1 dimensional hyperplane constrained to the sum s. Since, for all a and b, the problem can easily be rescaled to the case where a = 0 and b = 1, we will henceforth assume in this description that this is the case, and that we are operating within the unit n-dimensional "cube".
This is the implementation (© Roger Stafford):
function [x,v] = randfixedsum(n,m,s,a,b)
% Rescale to a unit cube: 0 <= x(i) <= 1
s = (s-n*a)/(b-a);
% Construct the transition probability table, t.
% t(i,j) will be utilized only in the region where j <= i + 1.
k = max(min(floor(s),n-1),0); % Must have 0 <= k <= n-1
s = max(min(s,k+1),k); % Must have k <= s <= k+1
s1 = s - [k:-1:k-n+1]; % s1 & s2 will never be negative
s2 = [k+n:-1:k+1] - s;
w = zeros(n,n+1); w(1,2) = realmax; % Scale for full 'double' range
t = zeros(n-1,n);
tiny = 2^(-1074); % The smallest positive matlab 'double' no.
for i = 2:n
tmp1 = w(i-1,2:i+1).*s1(1:i)/i;
tmp2 = w(i-1,1:i).*s2(n-i+1:n)/i;
w(i,2:i+1) = tmp1 + tmp2;
tmp3 = w(i,2:i+1) + tiny; % In case tmp1 & tmp2 are both 0,
tmp4 = (s2(n-i+1:n) > s1(1:i)); % then t is 0 on left & 1 on right
t(i-1,1:i) = (tmp2./tmp3).*tmp4 + (1-tmp1./tmp3).*(~tmp4);
end
% Derive the polytope volume v from the appropriate
% element in the bottom row of w.
v = n^(3/2)*(w(n,k+2)/realmax)*(b-a)^(n-1);
% Now compute the matrix x.
x = zeros(n,m);
if m == 0, return, end % If m is zero, quit with x = []
rt = rand(n-1,m); % For random selection of simplex type
rs = rand(n-1,m); % For random location within a simplex
s = repmat(s,1,m);
j = repmat(k+1,1,m); % For indexing in the t table
sm = zeros(1,m); pr = ones(1,m); % Start with sum zero & product 1
for i = n-1:-1:1 % Work backwards in the t table
e = (rt(n-i,:)<=t(i,j)); % Use rt to choose a transition
sx = rs(n-i,:).^(1/i); % Use rs to compute next simplex coord.
sm = sm + (1-sx).*pr.*s/(i+1); % Update sum
pr = sx.*pr; % Update product
x(n-i,:) = sm + pr.*e; % Calculate x using simplex coords.
s = s - e; j = j - e; % Transition adjustment
end
x(n,:) = sm + pr.*s; % Compute the last x
% Randomly permute the order in the columns of x and rescale.
rp = rand(n,m); % Use rp to carry out a matrix 'randperm'
[ig,p] = sort(rp); % The values placed in ig are ignored
x = (b-a)*x(p+repmat([0:n:n*(m-1)],n,1))+a; % Permute & rescale x
return

Categories