is_double function in a while loop condition - php

I'm trying to get the fractional number count of a decimal number. I tried following simple code, but the loop runs forever.
$var = 123.456;
$fraction_count = 0;
echo $var, "<br>";
while (is_double($var)) {
$var *= 10;
$fraction_count++;
echo $var, "<br>";
}
I'm new to php so, forgive me if this is a stupid question!

Floating point numbers are not trivial to deal with (see the manual for more information). But you don't even need to deal with the number as such.
If you treat it as a string, you can explode() on the . and use strlen() on the second part to get the $fraction_count:
$var = 123.456;
$parts = explode('.', $var);
$fraction_count = strlen($parts[1]);
Since PHP doesn't save trailing 0s on numbers, this will work for 123.4560 as well, but be sure to input it as a number, "123.4560" will get you a wrong result.

Related

PHP Why does explicit typecast + 1 work, but not with an increment operator

Firstly, let's say for the sake of argument, the reasons why I want to do this is arbitrary and not solution specific.
I would like to explicitly cast a variable, regardless of input, and increment it after typecasting, not with the original variable. For example, not like this:
$num = "47 downvotes";
(int) ++$num;
I am looking for something similar to this psuedo-coded version, or a variation thereof:
$num = "value";
++((int) $num);
For PHP being loose, I was really hoping this to work, but I can't use the Pre-increment operator without creating another variable first.
$num = "value";
$cast = (int) $num;
echo ++$cast;
While testing, I found that PHP is loose enough for it to work by adding a digit however:
$num = "47 dogs";
echo ((int) $num) + 1;
I also understand my first example, isn't wrong, but again, for arbitrary reasons, I need to make sure it has been casted prior to incrementing/decrementing.
So the question is, why is PHP loose enough for the latter to compile?
If you could provide resources or links to any reputable reading material I would appreciate that as well.
With explicit typecasting you have to assign the result to a variable. In your examples, you are trying to increment variables when they are strings, which fails or doesn't produce the result you expect in combination with typecasting.
Look at your original example:
<?php
$num = "47 downvotes";
echo $num . PHP_EOL;
echo ++$num;
The result of incrementing a string isn't what you expect it to be:
47 downvotes
47 downvotet
So your original supposition is that PHP doesn't work when in fact it does.
$num = "47 downvotes";
echo (int) ++$num . PHP_EOL;
$num2 = "47";
echo (int) ++$num2;
Output:
47
48
The process of typecasting is inherently complicated, and has all sorts of behavior that can produce unexpected results, and just isn't the catchall dependable "fix your input" that will let you find the numeric portion of any string available to you in a single line of code, but that doesn't mean that PHP is flawed.

Correct the float values

I read some data from a csv file. Each line in the file has a float value. these values can be either:
.123 : starting with a period, so I need to add a zero before.
1,23: having a delimter comma ',' instead of period so I need to change that.
1.2e3 having an exponential-format so I need to convert it to decimal format.
I can't use the function number_format because I can't set the number of decimal points (the float numbers don't have a fixed length of the decimal part and we want to take them as they are to not lose data).
Here is what I tried so far; I built two functions, the first one filters the floats, the second one corrects them when the filter returns false:
function validateFloat($float){
if(!filter_var($float,FILTER_VALIDATE_FLOAT,array('flags' => FILTER_FLAG_ALLOW_FRACTION))){
return false;
}
}
function correctFloat($float){
if (validateFloat($float)==false){
$number = number_format($float,null,'.');
str_replace($number,'',$line);
}
}
I don't know how to build the correctFloat function. Any suggestions ? Appreciate it.
Your function can check if there is a comma and get the correct deliminator then use floarval on any other case
function change_format($value){
if(is_string($value)){
//has to be a string if using ','
$value= str_replace(",",".",$value);
}
return floatval($value);
}
echo change_format(.123) ."<br>";
echo change_format("1,23") ."<br>";
echo change_format("1.2e3");
Outputs:
0.123
1.23
1200

How to manage number values with points?

$val represents 1,949.58 from my sql
$sold = 50;
if ($val>$sold){
echo "true";
}
else
{
echo "false";
}
I get false. somehow 50 is bigger than 1,949.58 and this because of the ',' sign. I need some advices on how to manage this right. Thx
$val is interpreted by php to be a string. When doing the comparison, it's doing a string compare so you aren't going to get the results you expect.
You need to force them to be a floating point type. Look at http://php.net/manual/en/function.floatval.php Specifically the comments on that function.
Something like this should work:
function floatvalue($value) {
return floatval(preg_replace('#^([-]*[0-9\.,\' ]+?)((\.|,){1}([0-9-]{1,2}))*$#e', "str_replace(array('.', ',', \"'\", ' '), '', '\\1') . '.\\4'", $value));
}
You need to convert these values to floats instead of strings. Right now you're doing string comparisons and not numerical comparisons. The following converts those strings to floating values.
$val = parseFloat('1,949.58'.replace(/\,/g,""))
$sold = parseFloat('50')
The .replace removes the "," from your original string before it's parsed to a Float.

XOR two hex strings

I want to XOR two strings (hex-encoded) in php.
I have tried using operator ^, but I get only 0.
How can I do that? Why is it wrong?
<?php
$s1 = 'ABCDEF1234567890';
$s2 = '0987654321ABCDEF';
$x = bin2hex(pack('H*',$s1) ^ pack('H*',$s2));
?>
$x = dechex(hexdec($s1) ^ hexdec($s2));
http://codepad.org/fgRfAPAI
The problem, that you initially had is, that a hex-string is in fact a string. When you use binary operators on strings, it uses the character-codes as byte value.
You need to decode them with hex2bin() before you apply the XOR ^ operator.
Update: I always forget that this function requires PHP/5.4 or greater, which can be an issue. In such case, you need to use the not very intuitive pack() function:
$binary = pack('H*', $hexadecimal);
Based on #KingCrunch's answer here and the comments I wrote this simple loop to compare octets and build up the answer. Interestingly, this has the same result as #lawlor's answer.
$key1 = 'ABCDEF1234567890ABCDEF1234567890';
$key2 = '0987654321ABCDEF0987654321ABCDEF';
$key1_octets = str_split($key1, 2);
$key2_octets = str_split($key2, 2);
$xor = '';
foreach ($key1_octets as $id => $key1_octet) {
$xor .= dechex(hexdec($key1_octets[$id]) ^ hexdec($key2_octets[$id]));
}
print $xor;
print bin2hex(pack('H*',$key1) ^ pack('H*',$key2));
I'm not actually sure if either one is a valid result, but I put this forth for feedback and in case it helps someone else who is looking at #KingCrunch's answer without knowing how to deal with the octets.

Do the math sum of a text variable? (E.g 5865/100 )

I have a variable that is...
$whatever = "5865/100";
This is a text variable.
I want it to calculate 5865/100 , so that I can add it to other numbers and do a calculation.
Number_format doesn't work, as it just returns "5,865". Whereas I want it to return 58.65
I could do...
$explode=explode("/",$whatever);
if(count($explode)=="2") {
$whatever = $explode[0]/$explode[1];
}
But it seems rather messy. Is there a simpler way?
Evaluate as PHP expression, but first check if it contains only digits and operators and space, and suppress any errors.
if (preg_match('/^[\d\+\-\/\*\s]+$/', $s)) {
#eval('$result = ' . $s . ';');
}
You can use the eval function to evaluate a string as code. However, you have to be careful as to where this code comes from because it will execute anything passed to it, not just simple math. If you knew your string contained a mathematical formula, you could do the following
$answer = 0;
$whatever = "5865/100";
eval ('$answer = ' . $whatever . ';');
print($answer);

Categories