This question already has answers here:
How to mathematically evaluate a string like "2-1" to produce "1"?
(9 answers)
Closed 3 years ago.
I am dealing with exif data acquired via php , and I see that the DPI of a scanned image can return 300/1 or 600/1 for example
I am not sure if this is normal but google tells me it is common. I do not know if this means I may see 300/2 (150DPI)
When I get this variable from exif, I want to treat it as a math problem that needs simplifying or in math terms 300 / 1 =300 therefore 300. As it is a string I have no idea how to tell php to simplify the math in the string.
Any ideas?
Assuming the string contains something like 300 It sounds like you're looking to cast your string to an integer with something like (int)$exif_string. If it contains something like 300/1, you can use substr($exif_string, 0, 3) to grab only the first three characters.
Once you have an integer variable, you can make your calculations on it:
$dpi = (int)substr($exif_string, 0, 3);
$dpi_value = $dpi / 300;
eval() would be a possible alternative, though I would recommend against this, due to the fact that it can allow arbitrary execution of code.
Related
This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 3 years ago.
Am having an issue where PHP expands the float value e.g. 241.09 becomes 241.0899999999. The issue is, the expanded value is included in a signature, thus the expansion is causing my signature to have a mismatch when matching with the actual data which has the original unexpanded form. How do I prevent the rounding off? My code section is as below:
round(floatval($resultParams["AvailableFunds"]), 2)
Somehow, even after applying the round function, the expansion still occurs. How do I prevent that??
It's caused by the PHP Floating point precision:
Floating point numbers have limited precision.
A solution may be to use only integer, e.g. save the float 123.45 as 12345 and when you need to use display it divide it by 100 and pass it to the number_format function:
$myNumView = number_format($myNum/100, 2, '.', '')+0;
By doing this, number_format returns a string formatted as 1234567.89, then by doing +0 PHP converts it to float (due to the PHP Type Juggling) and removes the rightmost 0 in the decimal part of the number:
$a = '35';
$b = '-34.99';
echo $myNum = ($a + $b);
echo '<br>';
echo $myNumView = number_format($myNum, 4, '.', '')+0;
returns:
0.009999999999998
0.01
And also, why does you get AvailableFunds from a string with floatval? It seems that AvailableFunds is a string containing the amount of fund and other text. I think this is a bad implementation on how saving the fund amount. It's better to save the value as is in a dedicated field as float.
I've read all over about arithmetic regarding floating point numbers, but I'm just trying to accurately store the darn things.
I have a mysql field with the type of DECIMAL (40,20).
I am saving a value in php of 46457.67469999996. After updating the record with this value, the end result is 46457.67470000000000000000. Not sure why it's being rounded at all just being saved to the database.
The value is not being converted to a string or anything beforehand. The field value that is passed into PDO is the value I expected to be saved and it is returned as a float... Perhaps it's because I'm saving a PHP float to a mysql decimal type where the rounding is occurring?
What am I missing here?
EDIT: Added example code that has the issue
// Query placeholder variables. Hard-coded for the example test
$query_vars = array(
":vendor_id" => 33154,
":year" => 2018,
":coop_committed_dollar" => 46457.67469999996,
":coop_committed_dollar_update" => 46457.67469999996
);
$statement = " INSERT INTO vendor_data_yearly
(vendor_id, year, coop_committed_dollar) VALUES
(:vendor_id, :year, :coop_committed_dollar)
ON DUPLICATE KEY UPDATE
coop_committed_dollar = :coop_committed_dollar_update;";
$query = $connection->conn->prepare($statement);
$query->execute($query_vars);
When I run this, the resulting value of coop_committed_dollar is 46457.67470000000000000000. This code is legit all I am doing.
Possible solution
// Note that I am casting the string using the BC Math library.
// I dunno how to just initialize the number (lame documentation), so I'm adding 0 to it.
$number = "46457.674699999967";
$number = bcadd("46457.674699999967", 0, 20);
$query_vars = array(
":vendor_id" => 33154,
":year" => 2018,
":coop_committed_dollar" => $number,
":coop_committed_dollar_update" => $number
);
$statement = " INSERT INTO vendor_data_yearly
(vendor_id, year, coop_committed_dollar) VALUES
(:vendor_id, :year, :coop_committed_dollar)
ON DUPLICATE KEY UPDATE
coop_committed_dollar = :coop_committed_dollar_update;";
$query = $conn->prepare($statement);
$query->execute($query_vars);
This results in the number as expected in the DB.
ONLY SOLUTION I FOUND TO WORK CORRECTLY
The data I am working with is passed in via ajax. I had to take a few steps to get this to work correctly.
Use ini_set('precision', 20);
Manually set the data in question to be a string BEFORE sending it via ajax so PHP would not round it, extended with extra floating point madness, padd it, etc.
I found that PHP would just not let me reliably work with large numbers coming from a variable set outside the script's scope (ajax). Once PHP got it's hands on the number, it would do what it had to do in order to make it make sense as a float.
If anyone has a better solution for this particular scenario I'm all ears and eyes :)
The problem is that PHP's precision is not allowing you to store the exact number you think you are storing.
When you set ":coop_committed_dollar" => 46457.67469999996
PHP is actually storing it as a different value, depending on the precision.
The solution is to store the value in PHP as a string instead of a float.
Since your question is: "what am I missing", I will try to provide an answer.
Basically it comes down to storing floats internally using binary representation. Since 46457.67469999996 cannot be exactly in binary (it ends up with an infinite number, similar to 33% (.3333...) in base-10), the closest rounding is used based on PHP's precision (set in php ini).
I was given a great explanation in this question that I asked a while back.
In your particular case, it also seems that the value that you are sending via AJAX is being stored as a float when parsed by PHP on the server-side. You want it to be stored as a string instead. If you're using json_decode, add this option: JSON_BIGINT_AS_STRING.
This question already has an answer here:
Convert exponential to a whole number in PHP [duplicate]
(1 answer)
Closed 7 years ago.
I have data from csv, the contents of the column id look like this 6.61884E+17 6.61881E+17 6.61878E+17
This code not work, the results of this code remains the same :(
$a = '6.61884E+17';
$b = (string) floatval($a);
How to convert 6.61884E+17 to string ?
Update :
I try number_format(6.61884E+17,0,'','') and get 661884000000000000 as result. . my expected result is 661883847445868544
You want the number 661883847445868544 to be extracted from 6.61884E+17.
This isn't possible for you because of "integer overflow".
PHP handles this for you by converting it into a float (it's stupid because you can't perform basic arithmetic on them).
Now, if you run echo strval(661883847445868544); and get the same value back, you are running PHP 64 bit, and can handle that number. However, what is clear is that the program that created the CSV is 32 bit, and the largest integer values are:
2,147,483,647 signed
4,294,967,295 unsigned
After the value 6.61884E+17 is dumped, precision after the 6th digit is lost, and there is nothing you can do to bring it back. Sorry.
Maybe the question is simple, but I can't find the answer.
What I need to do is to round number to 2 places after comma.
Im using this:
round(($data/$count*100), 2)
And when I get number like:
60.36036036036012 and : 37.83783783783808 is OK, because it's: 60.36 and 37.84
But why this:
1.8018018018018036
Is rounded to this:
1.8000000000000003
How to round always to 2 places, after comma?
You should get 1.8 unless you use something like old PHP version with some sort of related bugs. Still, if you want to see 1.80 you need to format output string, otherwise trailing zero will be stripped by default. The most flexible approach would be to use sprintf() formatting, like this:
$val = 1.8000000000000003;
printf("%.02f", round( $val, 2 ));
which would produce
1.80
The key is "%.02f" which means you want to format (f)loating point value, with two digits after dot, padded with 0 when needed (like this case).
See the sprintf() docs for more about available formatting possibilites.
Use PHP NumberFormatter class http://es.php.net/manual/es/class.numberformatter.php
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What does a leading zero do for a php int?
I am just a beginner in php. I tried to write program for print the given number as reverse. For example if i use 123 as input the result should be 321. I tried the following code. It works fine. But if the given input is 0123 the output is 38. I couldn't correct it. How can i correct my code? here is my code.
<?php
$n=123;
$b=0;
while($n>=1)
{
$b=$b*10+$n%10;
$n=$n/10;
}
echo $b;
?>
When you add a 0 to the beginning of your number, PHP treats the number as octal.
Octal 123 is decimal 83, which correctly changes to 38.
Just use the dynamic nature of PHP not much caring about the difference between numbers and strings:
echo strrev(123);
http://www.php.net/manual/en/function.strrev.php
Yes, it's because the numbers that are starting with 0 are considered in base 8, so 0123 is in fact 83 in base 10.
So, your algorithm is correct for integer numbers - if you want the revert of 0123 to be 3210, you could simply revert it as a string and you can simply use the strrev function
I think your math is the problem. You should have parenthesis around the multiplier and mod.
<?php
$num=6541020;
$revnum=0;
do{
$revnum=($revnum *10)+($num % 10);
$num=(int)($num / 10 );
}while($num>0);
echo $revnum;
?>
http://www.weberdev.com/get_example.php3?ExampleID=4879
you could use something like this:
<?php
$rprint = function ($nr) use (&$rprint)
{
echo $nr%10;
if($nr > 10)
{
$rprint($nr/10);
}
};
$rprint(12364);
?>
Edit 1:
OR you could use strings instead of numbers. As I suppose it was already suggested.
(I was a bit out of the subjects)
the integer with the leading zero is always treated as octal in php. So just make it as a string and use the buitin php function strrev()