PHP:将任何浮点数格式化为十进制扩展
我想创建一个函数formatFloat(),它接受任何浮动并将其格式化为十进制扩展字符串.例如:
formatFloat(1.0E+25); // "10,000,000" formatFloat(1.0E+24); // "1,000" formatFloat(1.000001); // "1.000001" formatFloat(1.000001E-10); // "0.0000000001000001" formatFloat(1.000001E-11); // "0.00000000001000001" 初步想法 简单地说casting浮点到一个字符串将不起作用,因为对于大于约1.0E 14或小于约1.0E-4的浮点数,PHP在scientific notation而不是decimal expansion中呈现它们.
number_format(1.0E+25); // "10,905,969,664" number_format(1.0E+24); // "999,999,983,222,784" 对于小浮点数,难点在于选择要求的小数位数.一个想法是要求大量的十进制数字,然后 number_format(1.000001,30); // "1.000000999999999917733362053696" number_format(1.000001E-10,30); // "0.000000000100000099999999996746" number_format(1.000001E-11,30); // "0.000000000010000010000000000321" 问题是浮点数具有limited precision,并且通常无法存储文字的确切值(例如:1.0E 25).相反,它存储可以表示的最接近的可能值. number_format()揭示了这些“最接近的近似值”. Timo Frenay的解决方案 我在
$result = sprintf(sprintf('%%.%dF',max(15 - floor(log10($value)),0)),$value); 关键部分是使用 有一些需要修复的错误: >该代码不适用于负浮动. 我最好的尝试 这是我提出的最佳解决方案.它基于Timo Frenay的解决方案,修复了错误,并使用ThiefMaster’s regex修剪多余的0: function formatFloat($value) { if ($value == 0.0) return '0.0'; $decimalDigits = max( 13 - floor(log10(abs($value))),0 ); $formatted = number_format($value,$decimalDigits); // Trim excess 0's $formatted = preg_replace('/(.[0-9]+?)0*$/','$1',$formatted); return $formatted; } Here’s an Ideone demo有200个随机浮点数.代码似乎适用于小于约1.0E 15的所有浮点数. 有趣的是,即使是非常小的浮点数,number_format()也能正常工作: formatFloat(1.000001E-250); // "0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000001" 这个问题 我对formatFloat()的最佳尝试仍然遇到这个问题: formatFloat(1.0E+25); // "10,664" formatFloat(1.0E+24); // "999,784" 有没有一种优雅的方法来改进代码来解决这个问题?
这段代码
seems to do the job too.我不认为我设法使它比你的更优雅,但我花了很多时间在它上面,我不能把它扔掉:)
function formatFloat( $value,$noOfDigits = 14,$separator = ',',$decimal = '.' ) { $exponent = floor(log10(abs($value))); $magnitude = pow(10,$exponent); // extract the significant digits $mantissa = (string)abs(round(($value / pow(10,$exponent - $noOfDigits + 1)))); $formattedNum = ''; if ($exponent >= 0) { // <=> if ($value >= 1) // just for pre-formatting $formattedNum = number_format($value,$noOfDigits - 1,$decimal,$separator); // then report digits from $mantissa into $formattedNum $formattedLen = strlen($formattedNum); $mantissaLen = strlen($mantissa); for ($fnPos = 0,$mPos = 0; $fnPos < $formattedLen; $fnPos++,$mPos++) { // skip non-digit while($formattedNum[$fnPos] === $separator || $formattedNum[$fnPos] === $decimal || $formattedNum[$fnPos] === '-') { $fnPos++; } $formattedNum[$fnPos] = $mPos < $mantissaLen ? $mantissa[$mPos] : '0'; } } else { // <=> if ($value < 1) // prepend minus sign if necessary if ($value < 0) { $formattedNum = '-'; } $formattedNum .= '0' . $decimal . str_repeat('0',abs($exponent) - 1) . $mantissa; } // strip trailing decimal zeroes $formattedNum = preg_replace('/.?0*$/','',$formattedNum); return $formattedNum; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |