浮点数与字符串的无损转换:可能吗?
这个问题涉及到C/x86上使用的IEEE标准浮点数。
是否可以将任何数字(即排除 NaN 等特殊值)浮点数或双精度数表示为十进制字符串,以便将该字符串转换回浮点数/双精度数始终会准确生成原始数字?
如果不是,什么算法告诉我给定的数字是否会出现转换错误?
如果是这样,请考虑这一点:某些十进制分数在转换为二进制时,在数值上不会与原始十进制值相同,但反之则不然(因为二进制具有有限精度,因此任何十进制扩展都是有限且完美的,如果不是)截断),所以这是另一个问题......
是否有必要在十进制表示中引入故意错误,以欺骗 atof
(或其他)函数产生准确的原始数字,或者将天真的,不被截断的toString
函数足够(假设通常可以进行精确转换)?
This question refers to the IEEE standard floating point numbers used on C/x86.
Is it possible to represent any numeric (i.e. excluding special values such as NaN) float or double as a decimal string such that converting that string back to a float/double will always yield exactly the original number?
If not, what algorithm tells me whether a given number will suffer a conversion error?
If so, consider this: some decimal fractions, when converted to binary, will not be numerically the same as the original decimal value, but the reverse is not true (because the binary has bounded precision so any decimal expansion is finite and perfect if not truncated), so here's another question...
Is it ever necessary to introduce deliberate errors into the decimal representation in order to trick the atof
(or other) function into yielding the exact original number, or will a naive, non-truncating toString
function be adequate (assuming exact conversion is possible in general)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
根据此页面:
因此,将
double
存储为至少 17 位数字(正确舍入)的十进制字符串将保证它可以转换回二进制double
,而不会丢失任何数据。换句话说,如果将每个可能的双精度值转换为 17 位数字的十进制字符串(正确舍入),它们将全部映射到不同的值。因此不存在数据丢失。
不过,我不确定单精度的最小截止值。但我怀疑它会是 8 或 9 位数字。
According to this page:
So storing a
double
as a decimal string with at least 17 digits (correctly rounded) will guarantee that it can be converted back to binarydouble
without any data loss.In other words, if every single possible double-precision value were to be converted to a decimal string of 17 digits (correctly rounded), they will all map to different values. Thus there is no data-loss.
I'm not sure on the minimum cut-off for single-precision though. But I'd suspect that it will be 8 or 9 digits.
鉴于 IEEE 格式只能表示有限数量的(二进制)数字,因此具有最低精度(参见 epsilon),因此您只需要有限数量的(十进制)数字。当然,如果实现(
strtod
、snprintf
)在{所有浮点数}和{每个浮点数一个十进制表示}集合之间具有恒等映射行为,那就更好了。Given that the IEEE format can only represent a finite number of (binary) digits, and therefore have a minimum accuracy (cf. epsilon), you will only need a finite number of (decimal) digits. Of course it is preferable if the implementation (
strtod
,snprintf
) has an identity mapping behavior between {all floats} and the set of {one decimal representation for each float}.在 java 中,可以通过构造中间 BigDecimal 对象将 double 转换为字符串:
此方法不存在区域设置问题。
但是,特殊的双精度值(Infinite、NaN)当然不起作用。
In java, it is possible to convert double from/to string, by constructing an intermediate BigDecimal object:
There is no locale issue with this method.
However, special double values (Infinite, NaN) will of course not work.
在 C 中,
printf
有一个标志a
,它将写入 IEEE 双精度数的精确表示,如这在手册页中记录。可以使用
scanf
读取结果。在 python 中,您可以使用其中任何一个
来保证打印可以转换回原始浮点数的表示形式
In C, there is a flag
a
to theprintf
that will write an exact representation of IEEE doubles, as inThis is documented in the man page. The result can be read with
scanf
.In python , you can use any of
this is guaranteed to print a representation that can be cast back to the original float