strange behaviour on php - php

Can some one please tell me why I get odd results rurning the following code?
<?php
class Bank
{
var $ID;
var $balance;
var $name;
function bank($name,$id,$balance=0)
{
$this->ID=$id;
$this->balance=$balance;
$this->name=$name;
}
function getBalance()
{
return $this->balance;
}
function setBalance($bal)
{
$this->balance=$bal;
}
function getId()
{
return $this->ID;
}
function setId($i)
{
$this->ID=$i;
}
)
$b= new bank(yaniv,027447002, 15000);
Now when I try to echo:
$b->ID
Instead of the expected 027447002 I get an odd 6180354,
but if I initiate the object like this :
$b=new bank(yaniv,'027447002',15000);
(notice I quoted the id property) it works OK.
Any suggestion why is this happening and what is the right way to fix it?

027447002 is in octal, as it prefixed with a zero. Convert that to decimal and you get 6180354!
See the manual page on integers for details.

Remove the leading zero, because it makes PHP treat the number as an octal number.

Because of the initial zero, it is interpreted as an octal number.
http://www.php.net/manual/en/language.types.integer.php
If the number should be left padded with zeros when printed (they are always a specific length) then you can use sprintf() to convert the stored integer to a zero padded string.

Numeric literals with leading zeroes are how you specify something in octal (base 8). If you write 27447002 instead of 027447002 you'll be fine.

Automatic base conversion. You don't even need all that class code to see this in action
echo 027447002;
The thing is that 027447002, in terms of numbers, is octal (base-8) - not a zero-filled decimal (base-10) integer.

I have one comment besides what everyone else is saying.
It appears you want a 0 padded number, right? A nine digit number that's padded with zeros on the left?
Think about using str_pad function. Like so:
...
function bank($name, $id, $bal=0)
{
...
$this->id = str_pad($id, 9, '0', STR_PAD_LEFT);
...
}
...
Then in your function you can call:
$b = new bank('John Doe', 12345678, 1.25);
If you output id, it would be padded
012345678

As everyone rightly said - this is considered an octal value by default. I think the class constructor should be testing that it is a valid integer, and initiating the class should typecast the value...
function bank($name, $id, $balance=0)
{
if (is_int($id))
$this->ID=$id;
else
throw new Exception('ID is not integer');
// and validate these too!
$this->balance=$balance;
$this->name=$name;
}
$b= new bank('yaniv', (int)027447002, 15000);
Hope that helps!

Related

PHP division adds a comma

I'm trying to convert cents to dollars (I don't need dollar sign, just value) but when I divide a number smaller than 100 by 100 I get a strange result.
Eg.: 1/100 give me 0,01.0
I don't need that comma, I need 0.01 as it should be.
I also tried number_format but it returns a string and when I cast the result to float I get the same strange value.
How can I fix it?
Thanks in advance for your help
This is the function I'm using:
public static function convertFromCents($value) {
if(is_numeric($value)) {
$value = $value/100;
} else {
$value = 0;
}
return $value;
}
This are the proof of what I'm saying:
It looks like what you see are messages of your IDE, not the real value of your variable.
In order to achieve what you want, you can simply use round function.
The second parameter is precision, which determines how many digits will appear after the point:
// return 0.33333333333333
echo 1/3;
// return 0.33
echo round(1/3, 2);

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);
}
?>

Why does C print different values than what PHP prints?

This is a complete noob question.
So here is my code in C,
#include<stdio.h>
int main()
{
int I, X=4;
double I0;
double COEFF1[7];
double COEFF2[9];
/*Coefficient 1 I0*/
COEFF1[0]=0.0045813;
COEFF1[1]=0.0360768;
COEFF1[2]=0.2659732;
COEFF1[3]=1.2067492;
COEFF1[4]=3.0899424;
COEFF1[5]=3.5156229;
COEFF1[6]=1.0000000;
/*Coefficient 2 I0*/
COEFF2[0]=0.00392377;
COEFF2[1]=-0.01647633;
COEFF2[2]=0.02635537;
COEFF2[3]=-0.02057706;
COEFF2[4]=0.00916281;
COEFF2[5]=-0.00157565;
COEFF2[6]=0.00225319;
COEFF2[7]=0.01328592;
COEFF2[8]=0.39894228;
if(X>=3.75)
{
I0=COEFF2[0];
for(I=1;I<9;I++)
{
I0=(3.75/X)*I0+COEFF2[I];
printf("%i\n", I0);
}
//return I0/(sqrt(X)*exp(-X));
}
else
{
I0=COEFF1[0];
for(I=1;I<7;I++)
{
I0=I0*(X/3.75)*(X/3.75)+COEFF1[I];
}
//return I0;
}
return 0;
}
And with little housekeeping, this is my translated code in PHP,
<?php
$coeff1 =array();
$coeff2 =array();
/*Coefficient 1 $i0*/
$coeff1[0]=0.0045813;
$coeff1[1]=0.0360768;
$coeff1[2]=0.2659732;
$coeff1[3]=1.2067492;
$coeff1[4]=3.0899424;
$coeff1[5]=3.5156229;
$coeff1[6]=1.0000000;
/*Coefficient 2 $i0*/
$coeff2[0]=0.00392377;
$coeff2[1]=-0.01647633;
$coeff2[2]=0.02635537;
$coeff2[3]=-0.02057706;
$coeff2[4]=0.00916281;
$coeff2[5]=-0.00157565;
$coeff2[6]=0.00225319;
$coeff2[7]=0.01328592;
$coeff2[8]=0.39894228;
$x = 4;
if($x>=3.75)
{
$i0=$coeff2[0];
for($i=1;$i<9;$i++)
{
$i0=(3.75/$x)*$i0+$coeff2[$i];
printf($i0."<br />");
}
//return $i0/(sqrt($x)*exp(-$x));
}
else
{
$i0=$coeff1[0];
for($i=1;$i<7;$i++)
{
$i0=$i0*($x/3.75)*($x/3.75)+$coeff1[$i];
}
//return $i0;
}
?>
But why won't they generate the same result?
http://imageshack.com/a/img59/3402/98ak.jpg
Please help. I'm stuck.
%i is the format specifier for int; I0 has type double but printf is being told to interpret it as int. You should use %f for doubles instead:
printf("%f\n", I0);
Maybe this bit might be useful too.
The difference in the output of the two programs can be attributed indeed to the line
printf("%i\n", I0);
in your C program where I0 is interpreted as an integer but its bit pattern was stored as a double type which uses different logic for organizing the bits (and in the standard variation also uses a different number of bits). What the printf function does is that it just takes whatever that bit pattern was (in the length of an integer) and prints it out like it was an integer - because you told it so (%i), hence the output of the program.
PHP uses dynamic type definition so your variables are interpreted in the context in which they are used (unless sometimes forced to be a certain type by casting or using settype()).
I.e.: $a = 1; will be an integer but if you do another assignment like $a += 0.5; it will be casted into a float automatically.

PHP: How to check if variable is a "large integer"

I need to check if a parameter (either string or int or float) is a "large" integer. By "large integer" I mean that it doesn't have decimal places and can exceed PHP_INT_MAX. It's used as msec timestamp, internally represented as float.
ctype_digit comes to mind but enforces string type. is_int as secondary check is limited to PHP_INT_MAX range and is_numeric will accept floats with decimal places which is what I don't want.
Is it safe to rely on something like this or is there a better method:
if (is_numeric($val) && $val == floor($val)) {
return (double) $val;
}
else ...
I recommend the binary calculator as it does not care about length and max bytes. It converts your "integer" to a binary string and does all calculations that way.
BC math lib is the only reliable way to do RSA key generation/encryption in PHP, and so it can easy handle your requirement:
$userNumber = '1233333333333333333333333333333333333333312412412412';
if (bccomp($userNumber, PHP_INT_MAX, 0) === 1) {
// $userNumber is greater than INT MAX
}
Third parameter is the number of floating digits.
So basically you want to check if a particular variable is integer-like?
function isInteger($var)
{
if (is_int($var)) {
// the most obvious test
return true;
} elseif (is_numeric($var)) {
// cast to string first
return ctype_digit((string)$var);
}
return false;
}
Note that using a floating point variable to keep large integers will lose precision and when big enough will turn into a fraction, e.g. 9.9999999999991E+36, which will obviously fail the above tests.
If the value exceeds INT_MAX on the given environment (32-bit or 64-bit), I would recommend using gmp instead and persist the numbers in a string format.
function isInteger($var)
{
if (is_int($var)) {
return true;
} elseif (is_numeric($var)) {
// will throw warning
if (!gmp_init($var)) {
return false;
} elseif (gmp_cmp($var, PHP_INT_MAX) >0) {
return true;
} else {
return floor($var) == $var;
}
}
return false;
}
I did
at the end of the function to check for numeric data.
return is_numeric($text)&&!(is_int(strpos($text,".",0)));
It will first check if it is numeric then check if there is no decimal in the string by checking if it found a position. If it did the returned position is an int so is_int() will catch it.
(strpos($text,".",0)==FALSE) would also work based on the strpos manual but sometimes the function seems to send nothing at all back like
echo (strpos($text,".",0));
could be nothing and the ==FALSE is needed.

Turn non decimal number into decimal number

I would like to know (as I current don't know and can't find the answer) how to turn a number without a decimal point into a number with a decimal point.
Here is what I would like to happen.
Input Output
1.20 1.20
1234 0.1234
0.23456 0.23456
4321 0.4321
So basically I need a PHP function that accepts an input number (from a form field, variable or whatever) and if a whole number add 0. (zero dot) to the beginning. If the input number already has a decimal leave as is (I will number_format afterwards).
This simple solution should do it.
function to_decimal($in){
return (stripos($in, ".")!==false)? $in: "0.".$in;
}
You could do something like this with is_float
if (!is_float($input))
{
$result = "0." . $input
}
Try this
function dPoint($number)
{
if(is_float($number))
{
return $number;
}
else
{
return "0.".$number;
}
}
Here's my solution without lame string concatenation
function leadingZero($num) {
if (!ctype_digit($num)) {
return $num/pow(10, strlen($num));
}
return $num;
}
// php> =leadingZero(4652)
// 0.4652
// php> =leadingZero(0.2)
// 0.2

Categories