php格式化浮点数,PHP:将任何浮点数格式化为十进制扩展

我想创建一个函数formatFloat(),它接受任何浮动并将其格式化为十进制扩展字符串.例如:

formatFloat(1.0E+25); // "10,000,000,000,000,000,000,000,000"

formatFloat(1.0E+24); // "1,000,000,000,000,000,000,000,000"

formatFloat(1.000001); // "1.000001"

formatFloat(1.000001E-10); // "0.0000000001000001"

formatFloat(1.000001E-11); // "0.00000000001000001"

初步想法

只要铸造浮子字符串都不行,因为花车比约大1.0E+14,或比约较小1.0E-4,PHP使得他们在科学记数法,而不是十进制扩展.

number_format()是尝试的明显的PHP功能.但是,大浮动会出现此问题:

number_format(1.0E+25); // "10,000,000,000,000,000,905,969,664"

number_format(1.0E+24); // "999,999,999,999,999,983,222,784"

对于小浮点数,难点在于选择要求的小数位数.一个想法是要求大量的十进制数字,然后rtrim()是多余0的数字.但是,这个想法是有缺陷的,因为十进制扩展通常不会以0s 结尾:

number_format(1.000001, 30); // "1.000000999999999917733362053696"

number_format(1.000001E-10, 30); // "0.000000000100000099999999996746"

number_format(1.000001E-11, 30); // "0.000000000010000010000000000321"

问题是浮点数的精度有限,通常无法存储文字的确切值(例如:) 1.0E+25.相反,它存储可以表示的最接近的可能值. number_format()揭示了这些"最接近的近似值".

Timo Frenay的解决方案

我发现这个评论深埋在sprintf()页面中,令人惊讶的是没有任何赞成票:

以下是如何使用16位有效数字打印浮点数,无论大小如何:

$result = sprintf(sprintf('%%.%dF', max(15 - floor(log10($value)), 0)), $value);

关键部分是使用log10()确定浮点数的数量级,然后计算所需的小数位数.

有一些需要修复的错误:

该代码不适用于负浮点数.

该代码不适用于极小的浮点数(例如:) 1.0E-100.PHP报告此通知:" sprintf():116位数的请求精度被截断为PHP最多53位数"

如果$value是0.0,那log10($value)就是-INF.

由于PHP浮点数的精度是"大约14位小数",我认为应该显示14位有效数字而不是16位数.

我最好的尝试

这是我提出的最佳解决方案.它基于Timo Frenay的解决方案,修复了错误,并使用ThiefMaster的正则表达式来修剪多余的0s:

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;

}

这是一个包含200个随机浮点数的Ideone演示.代码似乎适用于小于约的所有浮点数1.0E+15.

有趣的是number_format(),即使是非常小的浮动也能正常工作:

formatFloat(1.000001E-250); // "0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000001"

这个问题

我最好的尝试formatFloat()仍然遇到这个问题:

formatFloat(1.0E+25); // "10,000,000,000,000,000,905,969,664"

formatFloat(1.0E+24); // "999,999,999,999,999,983,222,784"

有没有一种优雅的方法来改进代码来解决这个问题?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值