php playing tricks when I send an "8" as an argument - php

I can't understand what the hack is going on with my code))) May be I just need more experience but... Let's get down to business:
I wrote a function which returns an array with some statistic data for my system, all I need is just to specify the arguments as Year, M, D. If I send something like getStatData(2016,07,07) - works fine, But just as i send something with a digit eight - it fails! eg.: getStatData(2016,07,08) Of course I have a file the fn requires, more over It works fine if a specify args as strings ('2016', '07', '08'); But this is ain't cool:D
The function:
function getStatData($y,$m,$d=false){
if(isset($y) && is_numeric($y) && isset($m) && is_numeric($m)){
$m=($m<10)? '0'.$m : $m;
if(isset($d)){
$d=($d<10)? '0'.$d : $d;
$y= 'days/'.$y;
$data = file_get_contents(STATDIR.'/'.$y.'/'.$m.'_'.$d.'.json');
}
else {
$data = file_get_contents(STATDIR.'/'.$y.'_'.$m.'.json');
}
return json_decode($data, true);
}
else return false;
}
Calling...
print_r(getStatData(2016,07,08)); //call with 08
ERROR: file_get_contents(core/statistic/days/2016/07_00.json): failed to open stream: No such file or directory

Numbers with a zero prefix are octal literals, rather than zero padded decimal integers. It seems that invalid octals are silently treated as 0 in PHP 5. You should pass in 7 and 8 in the example you have provided.
In PHP 7 you will get a parse error. E.g. Parse error: Invalid numeric literal in php shell code on line 1.

Pass arguments as string like print_r(getStatData('2016','07','08'));
As a side note use str_pad() function to format month and date to 2 digit value. Instead if isset($d) use if($d)
function getStatData($y,$m,$d=false){
if(isset($y) && is_numeric($y) && isset($m) && is_numeric($m)){
// use str_pad
$m=str_pad($m, 2, '0', STR_PAD_LEFT);
if($d){
// use str_pad
$d=str_pad($d, 2, '0', STR_PAD_LEFT);
$y= 'days/'.$y;
$data = file_get_contents(STATDIR.'/'.$y.'/'.$m.'_'.$d.'.json');
}
else {
$data = file_get_contents(STATDIR.'/'.$y.'_'.$m.'.json');
}
return json_decode($data, true);
}
else return false;
}
print_r(getStatData('2016','07','08'));

Related

Why PHP number_format() change the number? [duplicate]

I am working with huge numbers for website purposes and I need long calculation. When I echo a long number I don't get the correct output.
Example
// A random number
$x = 100000000000000000000000000;
$x = number_format($x);
echo "The number is: $x <br>";
// Result: 100,000,000,000,000,004,764,729,344
// I'm not getting the value assigned to $x
Your number is actually too big for php standard integers. php uses 64 bit integers which can hold values within range -9223372036854775808 (PHP_INT_MIN)
to +9223372036854775807 (PHP_INT_MAX).
Your number is about 87 bits long which simply is too much.
If you really need such big numbers you should use the php BC math types, explained in the manual: http://php.net/manual/en/ref.bc.php
If you just want to format a string formed like a huge number then use something like this:
function number_format_string($number) {
return strrev(implode(',', str_split(strrev($number), 3)));
}
$x = '100000000000000000000000000';
$x = number_format_string($x);
echo "The number is: $x\n";
// Output: The number is: 100,000,000,000,000,000,000,000,000
Edit:
Added strrev() to function because the string needs to be reversed before splitting it up (thanks to #ceeee for the hint). This ensures that the delimiter is placed at right position when length of input is not divisible by 3. Generated string needs to be reversed afterwards again.
Working example can be found at http://sandbox.onlinephpfunctions.com/code/c10fc9b9e2c65a27710fb6be3a0202ad492e3e9a
answer #maxhb has bug. if the input is '10000000000000000000000' the out put would be:
The number is: 100,000,000,000,000,000,000,00
Which is incorrect. So try below code:
function number_format_string($number, $delimeter = ',')
{
return strrev(implode($delimeter, str_split(strrev($number), 3)));
}
$x = '10000000000000000000000';
$x = number_format_string($x);
echo "The number is: $x\n";
// Output: The number is: 10,000,000,000,000,000,000,000
The largest integer that can be represented in a 64bit PHP install, compared to your number:
9,223,372,036,854,775,808 - largest possible signed 64bit integer
100000000000000000000000000 - your number
since you're exceeding the maximum number size, you can't expect to get useful results without using something like gmp/bcmath.
PHP does not yet support formatting long numbers, even when you always keep them as strings in your code (to avoid issues with PHP’s int type):
php > echo number_format('100000000000000000000000000');
100,000,000,000,000,004,764,729,344
php > echo number_format('3.14159265358979323846', 20);
3.14159265358979311600
The underlying ICU library supports formatting arbitrary precision decimal numbers, but PHP doesn’t use the relevant function yet – see request #76093.
http://php.net/manual/en/function.number-format.php
That is the solution:
<?php
# Output easy-to-read numbers
# by james at bandit.co.nz
function bd_nice_number($n) {
// first strip any formatting;
$n = (0+str_replace(",","",$n));
// is this a number?
if(!is_numeric($n)) return false;
// now filter it;
if($n>1000000000000) return round(($n/1000000000000),1).' trillion';
else if($n>1000000000) return round(($n/1000000000),1).' billion';
else if($n>1000000) return round(($n/1000000),1).' million';
else if($n>1000) return round(($n/1000),1).' thousand';
return number_format($n);
}
?>

Warning: str_repeat(): Second argument has to be greater than or equal to 0

I used this a while back to grab images from something but since I just tried using it again it is giving me this error:
Warning: str_repeat(): Second argument has to be greater than or equal to 0 in C:\inetpub\wwwroot\resource_update.php on line 121
This is the function for what its referring to so if anyone could help that would be great:
function consoleLogProgressBar($current, $size, $unit = "kb")
{
$length = (int)(($current/$size)*100);
$str = sprintf("\r[%-100s] %3d%% (%2d/%2d%s)", str_repeat("=", $length).($length==100?"":">"), $length, ($current/($unit=="kb"?1024:1)), $size/($unit=="kb"?1024:1), " ".$unit);
consoleLog($str, true);
}
Sounds like $length is returning a negative number? You could troubleshoot as follows:
$length = (int)(($current/$size)*100);
var_dump($length);
exit;
If that is in fact the case, then you could wrap it in the abs() function which will always return an absolute value:
$length = (int) abs(($current/$size)*100);
Of course, that is an ugly hack and doesn't solve the real issue. Either way, the first step is determine why $length isn't what you expect it to be.

How to solve a missing function argument

I am having an issue with my function. I can't seem to figure out why it works one way and not another.
When I go to the html source here http://adcrun.ch/ZJzV and place the javascript encoded string into the function It decodes the string just fine.
echo js_unpack('$(34).39(4(){$(\'29.37\').7($(34).7()-$(\'6.41\').7()-($(\'6.44\').7()*2))});$(\'29.37\').39(4(){3 1=-2;3 5=4(){9(1<0){$.26(\'15://25.22/21/24.20.19\',{14:\'46\',13:{16:18,17:23}},4(40){3 28=38(\'(\'+40+\')\');9(28.12&&1!=-2){45(31);3 8=$(\'<6 48="47"><27 36="#">49</27></6><!--43.42-->\');$(\'6.41 33#35\').57().60(\'59\',\'61\').30(8);8.62(4(){$.26(\'15://25.22/21/24.20.19\',{14:\'50\',13:{63:0,16:18,17:23,58:\'\'}},4(5){3 11=38(\'(\'+5+\')\');9(11.12&&1!=-2){52.51.36=11.12.53}});8.30(\'54...\')})}32{1=10}})}32{$(\'33#35\').56(1--)}};5();3 31=55(5,64)});',10,65,explode('|','|a0x1||var|function|rr|div|height|skip_ad|if||jj|message|args|opt|http|lid|oid|4106|php|fly|links|ch|188|ajax|adcrun|post|a|j|iframe|html|si|else|span|document|redirectin|href|fly_frame|eval|ready|r|fly_head|button|end|fly_head_bottom|clearInterval|check_log|continue_button|class|Continue|make_log|location|top|url|Loading|setInterval|text|parent|ref|margin|css|6px|click|aid|1000'));
But hen I use it like this echo js_unpack($full_code); it fails and gives me the following errors.
Warning: Missing argument 2 for js_unpack(),
Warning: Missing argument 3 for js_unpack(),
Warning: Missing argument 4 for js_unpack(),
Here is my php source that I am using.
//function to extract string between 2 delimiters
function extract_unit($string, $start, $end)
{
$pos = stripos($string, $start);
$str = substr($string, $pos);
$str_two = substr($str, strlen($start));
$second_pos = stripos($str_two, $end);
$str_three = substr($str_two, 0, $second_pos);
$unit = trim($str_three);
return $unit;
}
//html source
$html = file_get_contents('http://adcrun.ch/ZJzV');
//extract everything beteen these two delimiters
$unit = extract_unit($html, 'return p}(\'', '.split');
//full encoded strning
$string = $unit;
//the part here ne values ill be inserted
$expression = "',10,65,";
//inserted value
$insertvalue = "explode('|',";
//newly formatted encoded string
$full_code = str_replace($expression,$expression.$insertvalue,$string).')';
//function to decode the previous string
function js_unpack($p,$a,$c,$k)
{
while ($c--)
if($k[$c]) $p = preg_replace('/\b'.base_convert($c, 10, $a).'\b/', $k[$c], $p);
return $p;
}
//return decoded
echo js_unpack($full_code);
I didn't go through all your code, but there is a fundamental difference in your first 2 examples.
This line passes 4 arguments to the js_unpack function:
echo js_unpack( '$(......);', 10, 65, explode( '|', '|............' ) );
This line passes 1 argument to it:
echo js_unpack( $full_code );
I don't know if this is the root of your other problems, but it's a poor comparison to say "it works the first way but not the second way". The Warning is telling you exactly what you need to know: you are missing arguments.
Edit:
Based on your comment, I think you do not understand what is truly going on. You say you "copied the string and placed it in the function". This is incorrect. What you really copied was 1 string, 2 ints, and 1 array. You placed these 4 arguments in your function.
Maybe it helps if you format your functions this way:
echo js_unpack(
'$(......);', // <-- Argument #1 (a long string)
10, // <-- Argument #2 (int)
65, // <-- Argument #3 (int)
explode( '|', '|............' ) // <-- Argument #4 (array)
);
Compare that with:
echo js_unpack(
$full_code // <-- Just 1 argument
);
These are simply not the same signatures. Some PHP functions have default argument values, but this is not the case with js_unpack and it gives you a very clear warning that you are not calling it properly.

Convert a string containing a number in scientific notation to a double in PHP

I need help converting a string that contains a number in scientific notation to a double.
Example strings:
"1.8281e-009"
"2.3562e-007"
"0.911348"
I was thinking about just breaking the number into the number on the left and the exponent and than just do the math to generate the number; but is there a better/standard way to do this?
PHP is typeless dynamically typed, meaning it has to parse values to determine their types (recent versions of PHP have type declarations).
In your case, you may simply perform a numerical operation to force PHP to consider the values as numbers (and it understands the scientific notation x.yE-z).
Try for instance
foreach (array("1.8281e-009","2.3562e-007","0.911348") as $a)
{
echo "String $a: Number: " . ($a + 1) . "\n";
}
just adding 1 (you could also subtract zero) will make the strings become numbers, with the right amount of decimals.
Result:
String 1.8281e-009: Number: 1.0000000018281
String 2.3562e-007: Number: 1.00000023562
String 0.911348: Number: 1.911348
You might also cast the result using (float)
$real = (float) "3.141592e-007";
$f = (float) "1.8281e-009";
var_dump($f); // float(1.8281E-9)
Following line of code can help you to display bigint value,
$token= sprintf("%.0f",$scienticNotationNum );
refer with this link.
$float = sprintf('%f', $scientific_notation);
$integer = sprintf('%d', $scientific_notation);
if ($float == $integer)
{
// this is a whole number, so remove all decimals
$output = $integer;
}
else
{
// remove trailing zeroes from the decimal portion
$output = rtrim($float,'0');
$output = rtrim($output,'.');
}
I found a post that used number_format to convert the value from a float scientific notation number to a non-scientific notation number:
Example from the post:
$big_integer = 1202400000;
$formatted_int = number_format($big_integer, 0, '.', '');
echo $formatted_int; //outputs 1202400000 as expected
Use number_format() and rtrim() functions together. Eg
//eg $sciNotation = 2.3649E-8
$number = number_format($sciNotation, 10); //Use $dec_point large enough
echo rtrim($number, '0'); //Remove trailing zeros
I created a function, with more functions (pun not intended)
function decimalNotation($num){
$parts = explode('E', $num);
if(count($parts) != 2){
return $num;
}
$exp = abs(end($parts)) + 3;
$decimal = number_format($num, $exp);
$decimal = rtrim($decimal, '0');
return rtrim($decimal, '.');
}
function decimal_notation($float) {
$parts = explode('E', $float);
if(count($parts) === 2){
$exp = abs(end($parts)) + strlen($parts[0]);
$decimal = number_format($float, $exp);
return rtrim($decimal, '.0');
}
else{
return $float;
}
}
work with 0.000077240388
I tried the +1,-1,/1 solution but that was not sufficient without rounding the number afterwards using round($a,4) or similar

Check binary string, running into errors here

I'm using this function to check if binary is correct, I know it looks sloppy.. I'm not sure how to write the function that well.. but it doesn't seem to work!
If binary = 10001000 it says malformed, even though it's not.. what is wrong in my function?..
function checkbinary($bin) {
$binary = $bin;
if(!strlen($binary) % 8 == 0){
return 1;
}
if (strlen($binary) > 100) {
return 1;
}
if (!preg_match('#^[01]+$#', $binary)){ //Tried without !
return 1;
}
if (!is_numeric($binary)) {
return 1;
}
}
if (checkbinary("10001000") != 1) {
echo "Correct";
} else {
echo "Binary incorrect";
}
Why does this function always say 10001000 is incorrect?
if(!strlen($binary) % 8 == 0){ should be
if( strlen($binary) % 8 !== 0 ){
edit and btw: Since you're already using preg_match() you can simplify/shorten the function to
function checkbinary($binary) {
return 1===preg_match('#^(?:[01]{8}){0,12}$#', $binary);
}
This allows 0 - 12 groups of 8 0/1 characters which includes all the tests you currently have in your function:
strlen()%8 is covered by {8} in the inner group
strlen() > 100 is covered by {0,12} since any string longer than 8*12=96 characters would trigger either the first if or the >100 test
0/1 test is obvious
is_numeric is kinda superfluous
edit2: The name checkbinary might not be a perfect choice for the function. I wouldn't necessarily expect it to check for 8bit/byte alignment and strlen()<=100.
function checkbinary($bin) {
return preg_match('#^[01]+$#', $bin);
}
Some tests: http://www.ideone.com/3D9SQetX and http://www.ideone.com/1HCCtxVV.
I'm not entirely sure what you're attempting to achieve, but you might be able to get there via the following...
if($binaryString == base_convert($binaryString, 2, 2))...
In essence, this is comparing the results of a conversion from binary to binary - hence if the resultant output is identical, the input must be a valid binary string.

Categories