Compare floating numbers in PHP - php

I want to compare two floating numbers to see if $a is greater than $b.
So if:
$a = 1.23.94
$b = 1.23.90
If a is greater than b i want to echo "whatever".
Also need to allow for possibility of a number being 1.23.100 and comparing.
Thanks

to simply compare the two variables
if($a > $b) {
echo "whatever";
}
this link also may help you.
http://php.net/manual/en/language.types.float.php
notice that php has its floating point precision

Related

PHP- Maintain leading 0 in number [duplicate]

I need to add numbers in php without changing the number format like below
$a = "001";
$b = "5";
$c = $a+$b;
Now the result comes like "6" but I need "006" if $a is "01" then the result should be "06".
Thanks
Technically speaking, the $a and $b in your example are strings - when you use the addition operator on them they converted to integers which can't retain leading zeroes. More details on string-to-number conversion are in the manual
Something like this would do it (assuming positive integer strings with leading zeros)
#figure out how long the result should be
$len=max(strlen($a), strlen($b));
#pad the sum to match that length
$c=str_pad($a+$b, $len, '0', STR_PAD_LEFT);
If you always know how long the string has to be, you could use sprintf, e.g.
$c=sprintf('%03d', $a+$b);
Here, % introduces a placeholder, 03 tells it we want zero padded to fill at least 3 digits, and d tells it we're formatting an integer.
Hope this would help you:
<?php
$a="001";
$b="5";
$l=max(strlen($a),strlen($b));
$c=str_pad($a+$b, $l,"0", STR_PAD_LEFT);
echo $c;
?>
For common case. Your code should looks like this.
$a = someFormat($original_a);
$b = someFormat2($original_b); // $b has different format.
$c = someFormat($a + $b);
Or, you need write formatRecognition function.
$a = getValueA();
$b = getValueB();
$c = someFormat(formatRecognition($a), $a + $b);

Wrong PHP string equality

For some reason, PHP decided that if:
$a = "3.14159265358979326666666666"
$b = "3.14159265358979323846264338"
$a == $b is true.
Why is that, and how can I fix that?
It ruins my code.
The Problem
PHP converts strings (if possible) to numbers (source). Floating points have a limited precision (source). So $a == $b because of rounding errors.
The Fix
Use === or !==.
Try it
<?php
$a = "3.14159265358979326666666666";
$b = "3.14159265358979323846264338";
if ($a == $b) {
echo "'$a' and '$b' are equal with ==.<br/>";
} else {
echo "'$a' and '$b' are NOT equal with ==.<br/>";
}
if ($a === $b) {
echo "'$a' and '$b' are equal with ===.<br/>";
} else {
echo "'$a' and '$b' are NOT equal with ===.<br/>";
}
?>
Results in
'3.14159265358979326666666666' and '3.14159265358979323846264338' are equal with ==.
'3.14159265358979326666666666' and '3.14159265358979323846264338' are NOT equal with ===.
Note
When you want to do high precision mathematics, you should take a look at BC Math.
You could use === in the equality test.
$a = "3.14159265358979326666666666";
$b = "3.14159265358979323846264338";
if($a===$b)
{
echo "ok";
}
else
{
echo "nope";
}
This code will echo nope.
Comparing with == is a loose comparison, and both strings will be converted to numbers, and not compared right away.
Using === will perform a string comparison, without type conversion, and will give you the wanted result.
You can find more explanations in the PHP manual:
PHP type comparison tables
Comparison Operators
Try using $a === $b instead; you should never use == for string comparison.
Read PHP: Comparison Operators
If you compare a number with a string or the comparison involves
numerical strings, then each string is converted to a number and the
comparison performed numerically. These rules also apply to the switch
statement. The type conversion does not take place when the comparison
is === or !== as this involves comparing the type as well as the
value.
Others have recommended BC Math, but if you are doing floating point comparisons, the traditional way of comparing numbers is to see if they are the same to a reasonable error level
$epsilon = 1.0e-10;
if (abs($a - $b) < $epsilon) then {
// they're the same for all practical purposes
}
You should not to compare a float variable like that.
Try this:
bccomp($a, $b, 26)

Why is hash_hmac making different hashes for these two large numbers?

Why are hmac values different ? $a is equal to $b. I'm not sure what kind of error is causing this or if my logic is correct. Hmac_hash should convert any input to string to byte or hex and do it's job, tell me if I'm wrong.
Below example code.
Thank you.
<?php
$a = 1234567890000*1234567890000;
$b = gmp_mul("1234567890000","1234567890000");
$b = gmp_strval($b);
echo $a."<br/>".$b."<br/>";
$c = 2525;
echo ($a==$b)."<br/>";
echo hash_hmac("SHA512",$a,$c);
echo "<br/>";
echo hash_hmac("SHA512",$b,$c);
?>
Result
1.5241578750191E+24
1524157875019052100000000
1
973967436d3562150d60769b70a9010db21f89b114b9897430663dd195115b7893b9a6bd0e141cee301d23e2229afd6d39546630cd38f6fe7842073749f9ce3d
8bd1e7c837efaf8d51ed2d40354a020ee3c9663aa6bd4425c02b21ed02343185070216d37e54478ee78332af8e6fdecd51445fcee8cb04d4e51e4cc31283f9a9
When you compare $a and $b, the string inside $b is converted into an integer. Because the value is larger than what PHP can represent as an integer, it gets silently converted into a float instead. $a is a float. The floats are equal, which is why the compare succeeds.
hash_hmac converts the float in $a to a string instead of converting the string in $b into an integer which then overflows into a float. This is why the hashes differ.
If you want the compare to fail so that the behavior between it and hash_hmac is consistent, you'll want to cast $a into a string first or will want to use === to avoid converting data types.

How does the XOR trick to swap two variables really work on a string?

I just ran across this snippet of code for swapping the values of two variables in PHP:
<?php
$a = ‘bar’;
$b = ‘foo’;
$a = $a ^ $b;
$b = $a ^ $b;
$a = $a ^ $b;
echo $a . $b;
I understand the concept in binary; does this always work on strings? How?
PHP applies bitwise operators to strings by applying it to each character individually.
PHP: Bitwise Operators:
Be aware of data type conversions. If both the left-hand and right-hand parameters are strings, the bitwise operator will operate on the characters' ASCII values.
This will work if both strings have the same number of characters, or more precisely the same number of bytes. If the above quote is really precise, then it may only work for ASCII-only strings.

A function to get the smaller number

I have 2 variables each containing a number (integer). I would like to sort them to have the lowest number first and the second largest. For example:
$sortedVar = getSmaller(45, 62); // Will return 45
$sortedVar = getSmaller(87, 23); // Will return 23
Do you see what I want to do? Can you help me please?
Thanks :)
http://php.net/manual/en/function.min.php
min — Find lowest value..
If the first and only parameter is an array, min() returns the lowest value in that array. If at least two parameters are provided, min() returns the smallest of these values.
Note:
Values of different types will be compared using the standard comparison rules. For instance, a non-numeric string will be compared to an integer as though it were 0, but multiple non-numeric string values will be compared alphanumerically. The actual value returned will be of the original type with no conversion applied.
Caution
Be careful when passing arguments with mixed types values because min() can produce unpredictable results...
Use min() which supports any number of arguments as well as arrays.
$smallest = min(1,2); //returns 1
$smallest = min(4,3,2); //returns 2
$smallest = min(array(5,4)) //returns 4
function getSmaller($a, $b) {
return $a < $b ? $a : $b;
}
In plain english, if $a is smaller than $b, then return $a, else return $b.
Or as others pointed out, there's also a function for that, called min().
$sortedVar = $a < $b ? $a : $b;

Categories