fork(1) download
  1. <?php
  2.  
  3. function formatFloat($value)
  4. {
  5. $phpPrecision = 14;
  6.  
  7. if ($value == 0.0) return '0.0';
  8.  
  9. if (log10(abs($value)) < $phpPrecision) {
  10.  
  11. $decimalDigits = max(
  12. ($phpPrecision - 1) - floor(log10(abs($value))),
  13. 0
  14. );
  15.  
  16. $formatted = number_format($value, $decimalDigits);
  17.  
  18. // Trim excess 0's
  19. $formatted = preg_replace('/(\.[0-9]+?)0*$/', '$1', $formatted);
  20.  
  21. return $formatted;
  22.  
  23. }
  24.  
  25. $formattedWithoutCommas = number_format($value, 0, '.', '');
  26.  
  27. $sign = (strpos($formattedWithoutCommas, '-') === 0) ? '-' : '';
  28.  
  29. // Extract the unsigned integer part of the number
  30. preg_match('/^-?(\d+)(\.\d+)?$/', $formattedWithoutCommas, $components);
  31. $integerPart = $components[1];
  32.  
  33. // Split into significant and insignificant digits
  34. $significantDigits = substr($integerPart, 0, $phpPrecision);
  35. $insignificantDigits = substr($integerPart, $phpPrecision);
  36.  
  37. // Round the significant digits (using the insignificant digits)
  38. $fractionForRounding = (float) ('0.' . $insignificantDigits);
  39. $rounding = (int) round($fractionForRounding); // Either 0 or 1
  40. $rounded = $significantDigits + $rounding;
  41.  
  42. // Pad on the right with zeros
  43. $formattingString = '%0-' . strlen($integerPart) . 's';
  44. $formatted = sprintf($formattingString, $rounded);
  45.  
  46. // Insert a comma between every group of thousands
  47. $formattedWithCommas = strrev(
  48. strrev($formatted), 3, ','
  49. ),
  50. ','
  51. )
  52. );
  53.  
  54. return $sign . $formattedWithCommas;
  55. }
  56.  
  57. $randomFloats = array();
  58.  
  59. for ($i = 0; $i < 50; $i++) {
  60. $float = mt_rand() / mt_getrandmax();
  61. $float = round($float, mt_rand(0, 15));
  62. $float *= pow(10, mt_rand(-25, 25));
  63. if (mt_rand() / mt_getrandmax() > 0.5) {
  64. $float *= -1.0;
  65. }
  66. $randomFloats[] = $float;
  67. }
  68.  
  69. sort($randomFloats);
  70.  
  71. function formatFloat2(
  72. $value,
  73. $noOfDigits = 14,
  74. $separator = ',',
  75. $decimal = '.'
  76. ) {
  77.  
  78. $exponent = floor(log10(abs($value)));
  79. $magnitude = pow(10, $exponent);
  80.  
  81. $mantissa = (string)abs(round(($value / pow(10, $exponent - $noOfDigits + 1))));
  82. $formattedNum = '';
  83.  
  84. if ($exponent >= 0) { // <=> if ($value >= 1)
  85.  
  86. // just for pre-formatting
  87. $formattedNum = number_format($value, $noOfDigits - 1, $decimal, $separator);
  88.  
  89. // then report digits from $mantissa into $formattedNum
  90. $formattedLen = strlen($formattedNum);
  91. $mantissaLen = strlen($mantissa);
  92. for ($fnPos = 0, $mPos = 0; $fnPos < $formattedLen; $fnPos++, $mPos++) {
  93.  
  94. // skip non-digit
  95. while($formattedNum[$fnPos] === '-' || $formattedNum[$fnPos] === $separator || $formattedNum[$fnPos] === $decimal) {
  96. $fnPos++;
  97. }
  98. $formattedNum[$fnPos] = $mPos < $mantissaLen ? $mantissa[$mPos] : '0';
  99.  
  100. }
  101.  
  102. } else { // <=> if ($value < 1)
  103.  
  104. // prepend minus sign if necessary
  105. if ($value < 0) {
  106. $formattedNum = '-';
  107. }
  108. $formattedNum .= '0' . $decimal . str_repeat('0', abs($exponent) - 1) . $mantissa;
  109.  
  110. }
  111.  
  112.  
  113. // strip trailing decimal zeroes
  114. $formattedNum = preg_replace('/\.?0*$/', '', $formattedNum);
  115.  
  116. return $formattedNum;
  117.  
  118. }
  119.  
  120. foreach ($randomFloats as $float) {
  121. echo sprintf('%20s', $float) . "\n --> " . formatFloat($float) . "\n --> " . formatFloat2($float) . "\n";
  122.  
  123. }
  124.  
Success #stdin #stdout 0.01s 20568KB
stdin
Standard input is empty
stdout
       -8.435066E+20
 --> -843,506,600,000,000,000,000
 --> -843,506,600,000,000,000,000
         -9.5126E+19
 --> -95,126,000,000,000,000,000
 --> -95,126,000,000,000,000,000
            -8.0E+15
 --> -8,000,000,000,000,000
 --> -8,000,000,000,000,000
   -4.1229371001E+15
 --> -4,122,937,100,100,000
 --> -4,122,937,100,100,000
   -4.6191793562E+14
 --> -461,917,935,620,000
 --> -461,917,935,620,000
      -6221846899121
 --> -6,221,846,899,121.0
 --> -6,221,846,899,121
       -569101980221
 --> -569,101,980,221.0
 --> -569,101,980,221
     -807000407.8592
 --> -807,000,407.8592
 --> -807,000,407.8592
          -481739410
 --> -481,739,410.0
 --> -481,739,410
          -311472784
 --> -311,472,784.0
 --> -311,472,784
         -466478.662
 --> -466,478.662
 --> -466,478.662
               -6500
 --> -6,500.0
 --> -6,500
     -5127.345833521
 --> -5,127.345833521
 --> -5,127.345833521
       -6.0857161E-5
 --> -0.000060857161
 --> -0.000060857161
         -1.09986E-8
 --> -0.0000000109986
 --> -0.0000000109986
 -8.068224991704E-10
 --> -0.0000000008068224991704
 --> -0.0000000008068224991704
   -1.9264111956E-10
 --> -0.00000000019264111956
 --> -0.00000000019264111956
   -1.6576664064E-10
 --> -0.00000000016576664064
 --> -0.00000000016576664064
        -6.29644E-11
 --> -0.0000000000629644
 --> -0.0000000000629644
 -3.067853615185E-11
 --> -0.00000000003067853615185
 --> -0.00000000003067853615185
   -5.4441779831E-15
 --> -0.0000000000000054441779831
 --> -0.0000000000000054441779831
     -3.50411653E-17
 --> -0.0000000000000000350411653
 --> -0.0000000000000000350411653
        -2.74955E-22
 --> -0.000000000000000000000274955
 --> -0.000000000000000000000274955
       -2.008415E-24
 --> -0.000000000000000000000002008415
 --> -0.000000000000000000000002008415
     -1.52275077E-25
 --> -0.000000000000000000000000152275077
 --> -0.000000000000000000000000152275077
            -1.0E-25
 --> -0.0000000000000000000000001
 --> -0.0000000000000000000000001
 -9.398564211744E-26
 --> -0.00000000000000000000000009398564211744
 --> -0.00000000000000000000000009398564211744
  1.799545312207E-26
 --> 0.00000000000000000000000001799545312207
 --> 0.00000000000000000000000001799545312207
           2.829E-25
 --> 0.0000000000000000000000002829
 --> 0.0000000000000000000000002829
             9.0E-24
 --> 0.000000000000000000000009
 --> 0.000000000000000000000009
     9.097138214E-24
 --> 0.000000000000000000000009097138214
 --> 0.000000000000000000000009097138214
    1.1658440489E-18
 --> 0.0000000000000000011658440489
 --> 0.0000000000000000011658440489
      4.92904462E-18
 --> 0.00000000000000000492904462
 --> 0.00000000000000000492904462
        1.476054E-16
 --> 0.0000000000000001476054
 --> 0.0000000000000001476054
  3.967382690854E-16
 --> 0.0000000000000003967382690854
 --> 0.0000000000000003967382690854
       7.1239205E-12
 --> 0.0000000000071239205
 --> 0.0000000000071239205
            1.58E-11
 --> 0.0000000000158
 --> 0.0000000000158
           7.0246E-9
 --> 0.0000000070246
 --> 0.0000000070246
             5.36E-6
 --> 0.00000536
 --> 0.00000536
       83.3072581716
 --> 83.3072581716
 --> 83.3072581716
        292.12295091
 --> 292.12295091
 --> 292.12295091
     42888186.286617
 --> 42,888,186.286617
 --> 42,888,186.286617
        100000000000
 --> 100,000,000,000.0
 --> 100,000,000,000
       9781800000000
 --> 9,781,800,000,000.0
 --> 9,781,800,000,000
      33844000000000
 --> 33,844,000,000,000
 --> 33,844,000,000,000
        3.518748E+19
 --> 35,187,480,000,000,000,000
 --> 35,187,480,000,000,000,000
           6.194E+19
 --> 61,940,000,000,000,000,000
 --> 61,940,000,000,000,000,000
      4.66353538E+20
 --> 466,353,538,000,000,000,000
 --> 466,353,538,000,000,000,000
    4.3831979038E+22
 --> 43,831,979,038,000,000,000,000
 --> 43,831,979,038,000,000,000,000
           3.026E+23
 --> 302,600,000,000,000,000,000,000
 --> 302,600,000,000,000,000,000,000