Odd behavior with large double in PHP MySQL

Go To StackoverFlow.com

0

I have a database storing VIN numbers (stored as VID) for vehicles which are 17 characters in length. I am trying to increment to the next VID to display it on the page where a new vehicle can be added in the database. The VID field in the database is type bigint(17) and has auto_increment set.

$incr_query = "SELECT MAX(VID) FROM Vehicle";
$incr_result = mysql_query($incr_query);
$row = mysql_fetch_assoc($incr_result);
$vid = $row["MAX(VID)"] + 1;

Output:

print var_dump{$row);//array(1) { ["MAX(VID)"]=> string(17) "12345678123456788" }
print gettype($vid);    //double
print $vid;             //1.2345678123457E+16
print number_format(++$vid, 0, '.', '');       //12345678123456788
print number_format(--$vid, 0, '.', '');       //12345678123456788
print number_format($vid - 5, 0, '.', '');     //12345678123456784 

I'm not sure what's going on here. According to the PHP float manual:

"The size of a float is platform-dependent, although a maximum of ~1.8e308 with 
a precision of roughly 14 decimal digits is a common value"

EDIT:

So using bcadd, these are the outputs:

$vid = bcadd($vid, '1', 0); 
print "\n".$vid;                              //12345678123456789
print "\n".number_format($vid, 0, '.', '');   //12345678123456788
2012-04-05 00:45
by gwely
Well, it's not accurate enough, it seems? The number is more than 14 digits, so the estimation seems to hold for your architectur - Niklas B. 2012-04-05 00:48


0

The VID number might look like a "double" or "integer" or whatever but it isn't. Store it as string. Check out Skeet on Vimeo for an explanation. It starts around 6:10 and ends at, around, 10:00.

A bigint in the DB might do, but a double is a floating point and floating points are not intended to be used as discrete numbers; that's why they're floating points. I would go with string (varchar) all the way, up to the database. Using a bigint would encourage you/other developers to keep treating it as a "number" wich, in fact, it isn't (exactly).

2012-04-05 00:50
by RobIII
I see what you mean about discrete vs continuous. If I change it to a string in the database and in the script, how am I to increment it - gwely 2012-04-05 01:41
You could opt to keep the bigint in the DB for letting the DB handle the (auto)increment(ing). If you do, make sure you use use a string in your application. If you're going for string/varchar all-the-way as per my earlier suggestion you'll need a bit more (application)logic to increment the number with help from, for example, bcadd from BC Math or gmp_add from GMP - RobIII 2012-04-05 01:46
I updated my question. The number_format still outputs the same value for some reason - gwely 2012-04-05 01:53
Because numberformat tries to cast the value you're passing into it into some form of number (double probably) and then tries to format it. numberformat is not for formatting strings (of "bc_bignumbers" ; - RobIII 2012-04-05 08:23
@theyshookhands I actually don't see why you are using numberformat at all; you are passing the following arguments: the (string) $vid, then 0 for 0 decimal places, '.' for decimals separator (wich is of no use because you don't want decimal places, see previous argument passed in), and an empty thousands separator which would result in no thousands separator being used. So why bother using the numberformat at all? And, I checked, number_format tries to cast the first argument to float indeed - RobIII 2012-04-05 09:48
Well I was initially using it because it took the double out of scientific notation. But, yes, I have no use for it anymore I was just curious why it still displayed the initial value (after it has been incremented) - gwely 2012-04-05 14:06
Ads