My code is:
$arr=[02,05,07,08,09];
print_r($arr)
and output is:
Array
(
[0] => 2
[1] => 5
[2] => 7
[3] => 0
[4] => 0
)
Why it converts 08 and 09 to 0??
Numbers beginning with a zero are considered to be in base 8.
See PHP docs: Integers - Syntax.
To use octal notation, precede the number with a 0 (zero). To use hexadecimal notation precede the number with 0x. To use binary notation precede the number with 0b.
its considered as octal number. because you are starting it from zero.
$a = 1234; // decimal number
$a = -123; // a negative number
$a = 0123; // octal number (equivalent to 83 decimal)
$a = 0x1A; // hexadecimal number (equivalent to 26 decimal)
$a = 0b11111111; // binary number (equivalent to 255 decimal)
Related
I have about 200 lines in text file
values can be like
$array = ['.1','1.5','0.10','.8'....];
And I am looking specific regex pattern for replace .number like '.1' or '.8'
preg_replace('/\.(\d+)/','0${0}',$array[0]);
It's working, but for value 1.5 it's output is 10.5 and that's wrong.
If all of your values are float or integer expressions, then you can use bluntly use "start of string followed by literal dot": (Demo)
$array = ['.1', '1.5', '0.10', '.8'];
var_export(preg_replace('/^\./', '0.', $array));
If you need to make sure that the dot at the start of the string is followed by a digit, you could add a lookahead: (Demo)
var_export(preg_replace('/^\.(?=\d)/', '0.', $array));
Either way, you don't need to leverage any capture groups or backreferences.
It may be useful for you to know that preg_replace() will happily iterate your array on its own -- no additional loop needs to be written.
If you'd like to directly manipulate your txt file, just add a m pattern modifier so that ^ means the start of each line. (Demo)
$txt = <<<TEXT
.1
1.5
0.10
.8
TEXT;
echo preg_replace('/^\.(?=\d)/m', '0.', $txt);
Output:
0.1
1.5
0.10
0.8
Using \.(\d+) will get a partial match in 1.5 and matches .5
Then the replacement will be the untouched 1 plus 0 plus .5 resulting in 10.5
You can replace the values that start with a dot, and match a single following digit ^\.\d
If it should be the only value on the line, you can append an anchor for the end of the string as well ^\.\d+$
$array = ['.1','1.5','0.10','.8'];
foreach($array as $a) {
echo preg_replace('/^\.\d/','0$0', $a). PHP_EOL;
}
Output
0.1
1.5
0.10
0.8
See a PHP demo
If you have an array of values similar to the one you presented, then this can be solved without regular expressions. it's easy enough to use floatval,for example floatval('.8') will return 0.8. A general example is below:
$input = ['.1','1.5','0.10','.8'];
$output = array_map('floatval', $input);
print_r($output); // => Array ( [0] => 0.1 [1] => 1.5 [2] => 0.1 [3] => 0.8 )
Or if you need to strictly have strings:
$input = ['.1','1.5','0.10','.8'];
$output = array_map(function($item) {
return strval(floatval($item));
}, $input);
print_r($output); // => Array ( [0] => 0.1 [1] => 1.5 [2] => 0.1 [3] => 0.8 )
Or a short version with support for arrow functions (PHP >= 7.4):
$input = ['.1','1.5','0.10','.8'];
$output = array_map(fn($item) => strval(floatval($item)), $input);
print_r($output); // => Array ( [0] => 0.1 [1] => 1.5 [2] => 0.1 [3] => 0.8 )
If you need to normalize such values inside the text, then you can use preg_replace_callback + floatval
$input = "Test text: .1 + 1.5 = 1.6 and 000.10 - .8 = .2";
$output = preg_replace_callback("|\d*\.\d+|", fn($item) => floatval($item[0]), $input);
print_r($output); // => "Test text: 0.1 + 1.5 = 1.6 and 0.1 - 0.8 = 0.2"
You are not checking the context before . char.
You can check is the ' char is present before the . + digits:
preg_replace("/'\K\.\d+/",'0$0',$array[0]);
See the regex demo. Details:
' - a ' char
\K - forget the ' matched char
\. - a . char
\d+ - one or more digits
The 0$0 pattern replaces with 0 + the whole match value. Note the unambiguous ${0} backreference form is only required if the backreference is followed with a literal digit, not when it is preceded with it.
This function is converting an array which may contain strings to numbers which may or may not have a decimal.
function toNumberArray(array $stringArray) {
print_r ($stringArray);
echo "<hr>";
$n = [];
for ($i = 0; $i < count($stringArray); $i++) {
$n[] = settype ( $stringArray[$i],"float");
$x = (float) $stringArray[$i];
echo $x;
echo "<br>";
}
return $n;
}
print_r (toNumberArray(["1.123456789012345","2.2000000000000002","3.2999999999999998"]));
Results:
Array ( [0] => 1.123456789012345 [1] => 2.2000000000000002 [2] => 3.2999999999999998 )
1.1234567890123
2.2
3.3
Array ( [0] => 1 [1] => 1 [2] => 1 )
Question:
Why is settype not converting the string to a float?
How to convert if there are 14 or more places after the decimal?
It is converting to a PHP float which is a 64-bit IEEE floating point number. You are probably expecting that PHP uses a 32-bit IEEE floating point number for float and a 64-bit IEEE floating point number for a double'. But, in PHPfloatanddouble` are synonyms. (see the link in jorgonor's comment).
You could use PHP's round function to convert the 64-bit number to 6 or 7 decimal points to simulate the effect you are probably looking for. See http://php.net/manual/en/function.round.php
Is it possible to convert from numeric to an alphanumeric code like this:
a
b
c
d
..
z
1
2
3
4
..
aa
ab
ac
ad
..
az
a1
a2
a3
a4
..
aaa
aab
aac
aad
..
aaz
aa1
aa2
etc.
I'm trying to convert large numbers to smaller length alphanumeric strings.
Don't know why you want to do this specifically, but try changing the base from 10 to something like 32;
base_convert($number, 10, 32);
Then to convert back
base_convert($number, 32, 10);
As someone else pointed out - for very large numbers this may not work.
If you need to be able to handle very large numbers, check out this link:
How to generate random 64-bit value as decimal string in PHP
You can use base_convert() for changing the base of your number from 10 (decimal) to 36 (26 latin letters plus 10 arabic numerals).
The result will differ from your given example list. You have used the digits abc..xyz012..789, base_convert will use a diffent order 012..789abc..xyz.
// convert decimal to base36
echo base_convert($number_dec, 10 , 36);
// convert base36 to decimal
echo base_convert($number_b36, 36 , 10);
Translation
dec base36
0 0
1 1
...
9 9
10 a
11 b
...
34 y
35 z
36 10
37 11
..
45 19
46 1a
...
1295 zz
1296 100
1297 101
You could use dechex to convert the number to hex
http://php.net/manual/en/function.dechex.php
For example:
1000000 => f4240
1000001 => f4241
1000002 => f4242
1000003 => f4243
1000004 => f4244
1000005 => f4245
1000006 => f4246
1000007 => f4247
1000008 => f4248
1000009 => f4249
1000010 => f424a
1000011 => f424b
1000012 => f424c
1000013 => f424d
1000014 => f424e
1000015 => f424f
1000016 => f4250
1000017 => f4251
1000018 => f4252
1000019 => f4253
1000020 => f4254
To convert back, just use hexdec
http://php.net/manual/en/function.hexdec.php
base64_encode();
and for decode use
base64_decode();
Both dechex() and base_convert() will fail with large numbers. They are limited by the maximum size and precision of int and float types internally used during conversion.
The http://php.net/manual/pt_BR/function.base-convert.php discussion has some nice helper functions (see 2, 3) that can avoid this problem by using BC-functions to do the math. The BC extension can deal with arbitrarily large numbers.
I'm a little stumped here. I have 2 32-bit integers, one for the most significant bits & the other is the least. How do I find the decimal equivalent from those two in PHP?
Update:
I have tried the suggestion from #bwoebi and modified it a little. Here's the code:
$value=get64($msb, $lsb);
function get64($msb, $lsb) {
$count = count($lsb);
for($i=0; $i < $count; $i++) {
$value[$i] = bcadd(bcmul($msb[$i], bcpow(2, 32)), $lsb[$i] > 0?$lsb[$i]:bcadd(bcsub(bcpow(2, 32), $lsb[$i]), 2 << 30)); // $a most significant bits, $b least significant bits
}
}
Output:
msb=Array ( [0] => INTEGER: 0 [1] => INTEGER: 0 )
lsb=Array ( [0] => INTEGER: 143 [1] => INTEGER: 0 )
value=Array ( [0] => 2147483648 [1] => 2147483648 )
The output does not look right...I would have expected 143 as value[0]. Any input?
bcadd(bcmul($a, bcpow(2, 32)), $b >= 0?$b:bcsub(bcpow(2, 32), $b)); // $a most significant bits, $b least significant bits
should do the job. I am using the bc library as there maybe imprecisions when working with normal operators on the 32 bit systems (It would be converted to float).
You can use the BC Math or GNU Multiple Precision extensions to perform arithmetic with values too large for native PHP variables.
I was wondering how SplPriorityQueue works when priority is string or int. Quick example:
$queue = new \SplPriorityQueue();
$queue->insert('b', 5);
$queue->insert('c', 5);
$queue->insert('d', 1);
$queue->insert('a', 10);
$queue->insert('1', 'a');
$queue->insert('2', 'b');
print_r($queue);
Output:
Array
(
[5] => a
[4] => b
[3] => c
[2] => d
[1] => 2
[0] => 1
)
Question: why items with int priority are listed first (i.e. a b c d)? When priority is string (items 1 2), is b considered greater than a?
This is determined by SplPriorityQueue::compare(). The documentation states about its return value:
Result of the comparison, positive integer if priority1 is greater
than priority2, 0 if they are equal, negative integer otherwise.
Note:
Multiple elements with the same priority will get dequeued in no particular order.
Note, that the parameters priority1 and priority2 are declared as mixed and there is no mention of converting to int.
This means, the usual rules for > apply (see comparison operator documentation):
string compared to string: lexical comparison (numerical if both strings are numerical)
int compared to int: numerical comparison
string compared to int: string is converted to number, numerical comparison
(int)'a' and (int)'b' resolves to 0, this is why these items come last after all numbers.
These are the relevant comparisons for your example:
php > var_dump(1 > 'a');
bool(true)
php > var_dump(1 > 'b');
bool(true)
php > var_dump('b' > 'a');
bool(true)