Reputation: 45
I want to convert a decimal number to an integer by multiplying it by 10 until it gives me an integer.
Example: 0.2 should become 2 and 0.004 should become 4
Here is my function
function make_integer($num){
if (!is_int($num)){
$temp = $num;
while (!is_int($temp)){
$temp *= 10;
}
return $temp;
}
return $num;
}
I want
make_integer(0.2) => 2
Shouldn't the function stop when $temp becomes an integer? The function seems to be going in an infinite loop.
Could someone tell me why this isn't working please?
Upvotes: 2
Views: 316
Reputation: 6013
This will solve your problem
function make_integer($num){
if ((int)$num != $num){
$temp = $num;
while ((int)$temp != $temp){
$temp *= 10;
}
return $temp;
}
return $num;
}
The problem is that is_int
does not test if your value is an integer or not. It will test if its type is an integer or not. So is_int($var)
will do the same as if you ran gettype($var) == 'integer'
.
Some basic tests:
is_int((int) 0.57); # returns true, because the type is an int.
is_int((float) 4); # returns false, because the type is a float
is_int(10 * 0.2); # returns false, because int*float will be typecasted to a float
To make your code work, and to test if a value is an integer, you should cast your variable to an integer and then test if it is still equal to the original variable, like this:
(int) $var == $var; # will return true if the value is int
To fix your code, substitute the !is_int($num)
with (int) $num != $num
and !is_int($temp)
with (int) $temp != $temp
, just like the code in the short answer above.
But, I can't resist to give an alternative solution to your problem. Personally, I would opt to use recursion for this problem. Like this:
function make_integer($num) {
return (int)$num == $num ? $num : make_integer($num * 10);
}
Or if you dislike the ternary operator:
function make_integer($num) {
if ((int)$num == $num)
return $num; # We're all done!
else
return make_integer($num * 10); # Try to increase by 10
}
The type casting of php will take some time to learn. In general, PHP will allways try to type cast if it can. When you multiply an integer with a float, the result will be a float, even if it "looks" like an integer.
So try this code and pay special attention to the output:
$var = 0.03;
var_dump($var); # float(0.03)
var_dump(gettype($var)); # string(6) "double"
var_dump(is_int($var)); # bool(false)
Now, if you multiply by the integer 100, php will stick the float, as <float>*<int>
multiplication allways will result in a float, regardless of the value.
$var *= 100; # (100 * 0.03)
var_dump($var); # float(3)
var_dump(gettype($var)); # string(6) "double"
var_dump(is_int($var)); # bool(false)
Note that the value is a natural number, but the type is still a float, and thus is_int will not return true.
To test if a actual value of a variable is indeed an integer, we will need to do our own little trick with manual typecasting.
$var = 2.33;
var_dump($var); # float(2.33)
$var = (int) $var;
var_dump($var); # int(2)
Note that when we tried to cast a float to an int the value changed. But if we try to cast a float that is an integer to an int, the value remains unaffected, only the type gets changed:
$var = 2.0;
var_dump($var); # float(2)
$var = (int) $var;
var_dump($var); # int(2)
And now, remember how <int>*<float>
resulted in a float? PHP will work in the same way when you do comparisons. In php, "2.0" == 2
will be true
because of this automatic typecasting. So when you do <int> == <float>
what really happens is (float)<int> == <float>
.
So what happens if we do (float)(int)0.3
. First we typecast 0.3 to int(0), then we typecast back to float(0). Obviously, float(0) == float(0.3)
will be false
. But (float)(int)3.0
will be cast first to int(3) then to float(3), which was the same value we started with.
$var = 3.0;
var_dump($var); # float(3)
$var = (int) $var;
var_dump($var); # int(3)
$var = (float) $var;
var_dump($var); # float(3)
So if we do (int) 3.0 == 3.0
, it will result in (float)(int) 3.0 == 3.0
which is true
.
So the way to test if a value is integer is to do
(int)$var == $var
Upvotes: 3
Reputation: 722
to resolve your problem, change the logic test.
Upvotes: 1
Reputation: 3517
This isn't the prettiest but it works.
function make_int($num){
//if it's not an int...
if(!is_int($num)){
//find out how many decimal places and store in a variable
$multiply = strlen(substr(strrchr($num, "."), 1));
//multiply the number by the power of the multiple.
$num *= (pow (10,$multiply));
return $num;
}
}
make_int(0.004);
Upvotes: 0