Tag: Floating point

  • PHP floats and locales

    I recently had a bug report in JFFNMS that the SLA checks were failing with bizarre calculations.  Things like 300% disk drive utilization and the like.  Briefly, JFFNMS is written in PHP and checks values that come out of rrdtool and makes various comparisons like have you used more than 80% of your disk or have there been too many errors.

    The logs showed strange input variables coming in, all were integers below 10.  I don’t know of many 1 or 3 kB sized disk drives. What was going on?  I ran a rrdtool fetch command on the relevant file and got output of something like 1,780000e+07 which for an 18GB drive seemed ok. Notice the comma, in this locale that’s a decimal point… hmm.

    In lib/api.rrdtool.inc.php there is this line around the rrdtool_fetch area:

    $value[] = ($line1[$i]=="nan")?0:(float)$line1[$i];

    A quick check and I was finding that my 1,7…e+07 was coming back as 1.  We had a float conversion problem.  Or more specifically, php has a float conversion problem.  I built a small check script like the following:

    setlocale(LC_NUMERIC,'pl_PL.UTF-8');
    $linfo = localeconv();
    $pi='3,14';
    print "Decimal is "$linfo[decimal_point]". Pi is $pi and ".(float)($pi)."n";
    print "Half is ".(1/2)."n";

    Which gave the output of:

    Decimal is “,”. Pi is 3,14 and 3

    Half is 0,5

    So… PHP is saying that decimal point is a comma and it uses it BUT if a string comes in with a comma, its not a decimal point. Really?? Are they serious here?  I tried various combinations and could not make it parse correctly.

    The fix was made easier for me because I know rrdtool fetch only outputs values in scientific notation. That means if there is a string with a comma, then it must be a decimal point as it could never be used for a thousands mark.  By using str_replace to replace any comma with a period the code worked again and didn’t even need the locale to be set correctly, or that the locale for the shell where rrdtool is run is the same as the locale in php.

    Enhanced by Zemanta