I have a simple calculator script for making calculations of facebook insights.
There is a function in my script called fb_growth where I pass two arguments in: one for the current month's data ($moc) and one for the previous month's data ($mop) and I am trying to find the growth percentage (positive or negative) between the 2. Here is my function script:
//Growth Calculator Function
function fb_growth($moc, $mop) {
if($moc>=$mop) {
$grp = ($moc/$mop);
$grf = ($grp - 1);
return $grf;
}
else if($moc<$mop) {
$grp = ($mop/$moc);
$grf = (1 - $grp);
return $grf;
}
}
The values I enter in are coming from a form that the user fills out. In this particular case, the numbers passed in are fb_growth($fbfi1, $fbfi2); where $fbfi1 equals the string '1719223' and $fbfi2 equals the string '1859867'. In this case, $moc is less than $mop, so 1719223 gets divided by 1859867, which should return 1.08180672315, but instead it returns 1, which then gets subtracted by 1 to get 0. What I want to end up with is '-.08180672315', which would be my growth percentage, but I cannot get it to give me this outcome. If I echo ("1859867"/ "1719223"); then I get 1.08180672315, but when the strings are held in the variables and I echo ("$fbfi2" / "$fbfi1"); then I get 1.
I tried settype() to a double and an int for $grf and for both $fbfi1 & 2 and same result. If I set $grf as a global and echo gettype(), it will give me the double or the int, but I still get the same value: 0. Is there something I can adjust in my php settings for this, or is there something wrong with my setup? I can't find any documentation. Help is MUCH appreciated, thank you!!
PHP does automatic casting, see the type juggling manual. Integer division yields integer result (hence the 1).
Cast the values before doing arithmetic calculations: (float) $var
And the problem was... comma's in the entry numbers!! I was inputing 123,456 instead of 123456. That's what you get when you just carelessly copy and paste sometimes..wow. Thanks for all the help though, I learned a lot about casting!
Related
In PHP i have define a variable with 19 digit long number and then print it. But it changes into exponential NUmber which is not acceptable in API Use. I need it as NUMBER. Here is an example of Problem.
$a = 1435483000000072013;
echo $a;
adn it returns 1.4354830000001E+18
Also, I have tried following function but it return wrong number
function output($x) {
$f = sprintf('%0.08f', $x);
$f = rtrim($f,'0');
$f = rtrim($f,'.');
return $f;
}
echo output(1435483000000072013);
this returns me 1435483000000071936 Number changes
So what is solution for this??
Champ, PHP doesn't have strictly typed variables, but it still has to decide whether your number is an int, a float or a double when it stores the information. And your number is larger than INT_MAX, so it's not going to fit into an integer format. That means the system has to bump it up to at least a float, which is where you're getting the exponential format from.
See NoGray's solution for how to fix it. Your number is still being stored, it's just being represented differently because your number is too big.
You can use number_format with an empty string for the thousands separator
e.g.
$a = 1435483000000072013;
echo number_format($a, 0, '.', '');
$a = 1.435483000000072013;
printf("%.18f",$a);
Problem is bit critical. Output I need is 2.9558577807620168e-12.
1#working.php
<?php
$a = 465.90928248188;
$b = 15.651243716447;
$c = 450.25803876543;
echo $a - $b -$c // output 2.9558577807620168e-12 as expected
?>
2#notworking.php
<?php
lot of arithmetic calculation almost 200-250 LoC
$array1_28x1[3]; // 465.90928248188
$array2_28x1[3]; // 15.651243716447
$array3_28x1[3]; // 450.25803876543
echo $array1_28x1[3] - $array2_28x1[3] - $array3_28x1[3];
// output -4.5474735088646E-13
?>
I Don't understand what is the issue. Can it be memory leak? I have done step by step debugging also but could not find any solution. And this is very important calculation so can not even ignore.
Note: There is no changes in the variable's value under those 250 LoC. I have dumped variables before the subtraction.
You did use 2 times the array2, so i think it is a typo.
when i execute this code it works:
<?php
$array1_28x1[3] = 465.90928248188;
$array2_28x1[3] = 15.651243716447;
$array3_28x1[3] = 450.25803876543;
echo $array1_28x1[3] - $array2_28x1[3] - $array3_28x1[3];
// output 2.955857780762E-12
The problem arises since you display your intermediate variables with only 14 significant digits. This hides 2 additional digits that are present in the original computation but missing in the reconstruction.
The general solution is to recognize that within the bounds of floating point arithmetic, you have effectively computed zero.
To get a reconstructable result you could convert the intermediate results to strings which are displayed and then those back to numbers. This will trivially give you results that can be reproduced from the displayed intermediate results.
As to having a result that is essentially floating point noise and thus represents zero, your scale/magnitude of inputs is 1000, which gives a absolute error scale resp. scale of floating point noise of 1e4*1e-16=1e-12. Both indicated results fall within this scale, i.e., both have to be considered to be zero.
I want to round a number to a specific number of significant digits - basically I want the following function:
round(12345.67, 2) -> 12000
round(8888, 3) -> 8890
I have the following, but there's a strange problem.
function round_to_sf($number, $sf)
{
$mostsigplace = floor(log10(abs($number)))+1;
$num = $number / pow(10, ($mostsigplace-$sf));
echo ($number / pow(10, ($mostsigplace-$sf))).' '.$num.'<BR>';
}
round_to_sf(41918.522, 1);
Produces the following output:
4.1918522 -0
How can the result of a computation be different when it's assigned to a variable?
Using the commenting-out binary search method of debugging, I narrowed this down.
Apparently the following line, in another function, in a totally different file even, is the problem.
$diff = date_diff(new DateTime($lastdate), new DateTime("NOW"));
If I comment that out, I get a correct result from my rounding function.
Can anyone tell me what the .... is going on here? This had me ripping my hair out for a day. It also caused other bugs that looked like memory stomps - I'd run a calculation that should produce a float foo, and foo would get used in other calculations that produced correct output, but echoing foo would show A.KIPGGGGGGGGG.
I am having trouble with a complex script which sometimes (About 2 or 3 times while calulating about 90'000 values), generates a '-0' and writes it into the database. I suspect it's a string (The values which are calulated can result in integers, floats or strings.)*
Is there any PHP calculation which might result in a '-0'?
* = Oh, how I miss strong typing sometimes...
Rounding a negative number toward positive infinity, as ceil() does, can produce -0.
echo ceil(-.7);
// -0
The same result comes with, e.g., round(-.2).
Both of these will resolve to true:
(-0 == 0)
(ceil(-.7) == 0)
While these will resolve to true and false, respectively:
(-0 === 0)
(ceil(-.7) === 0)
Edit: An interesting (and implemented) rfc can be read here.
As Gurdas says, you can have your strong typing in the database. That aside, I don't know the answer to your question but I know how would I approach the problem.
The problem, as I understand it, is that you don't know in which cases you get the '-0', which is a valid floating point representation of 0, by the way. So you have to find in which cases you are getting that. I'd take one of two routes:
Use Xdebug, raise an error in the database insertion code when the value is '-0' to get a stack_trace with arguments (use xdebug.collect_params=1)
Create an empty string at the beginning of the script, populating it with all the operations and operands being done as they are, with the result and line. Afterwards, in the insertion clause add an if ($value == '-0') { print $string; }
I put a check in a script that makes sure a total is correct. What it does is looks at the total as it is stored in the database and then using other variables, calculates what the total should be.
If these two values - the stored total and the calculated total - are not equal, it's a problem so I want it to send an email alert.
Here's the snippet of the code I use to do this:
$storedTotal = $row['total']; # Pulls from a varchar field in the database
$calculatedTotal = $subtotal + $tax + $shipping - $deduct;
# Make sure the stored total equals what it should (the calculated total)
if($storedTotal != $calculatedTotal) {
# Send an alert
mail("admin#domain.com","Total check fail","Stored total:$storedTotal \n\n Calculated total:$calculatedTotal \n\n");
}
It seems very simple, however, I repeatedly get emails from it that looks like this:
Stored total:23.40
Calculated total:23.40
As you can see, the two values appear the same.
Can anyone see any reason why they're not showing as equal? I'm not using a strict equality check so it shouldn't be getting tripped up on types.
It's most likely a floating point comparison error - there are probably some very insignificant digits which the default float -> string conversion routines think aren't worth printing but which are significant enough to cause the comparison to fail. You'll find dozens of similar questions on StackOverflow.
As these appear to be currency amounts, just check that they're within a tenth of a minor unit of each other:
$is_equal = (abs($val1 - $val) < 0.001);
Try converting and rounding before you compare them:
$storedTotal = round(floatval($storedTotal), 2);
$calculatedTotal = round(floatval($calculatedTotal), 2);
if ($storedTotal != calculatedTotal) {
...
I had the same problem - my simple data-consistency sanity checks were failing as a result. I used Alnitak's solution to implement this simple function:
function not_equals($val1, $val2)
{
return (abs($val1 - $val2) > 0.001);
}
Now my tests pass but I'm very unhappy. A programming language where 6.60 does not equal 6.60??? What else will PHP do to me? I want to go back to C++!
There must be something else that you are missing and we aren't seeing. Probably something related to the size of floats.
Because.
$test = "24.50";
$test2 = 24.50;
var_dump($test == $test2); // bool(true)