浮点数与字符串的无损转换:可能吗?

发布于 2024-12-28 14:45:47 字数 384 浏览 6 评论 0原文

这个问题涉及到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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

彡翼 2025-01-04 14:45:47

根据此页面

实际上,IEEE754-1985 标准规定 17 位十进制数字是
在所有情况下都足够了。不过好像标准有点
对于一致的实现是否必须保证无损含糊其辞
使用 17 位数字时的转换。

因此,将 double 存储为至少 17 位数字(正确舍入)的十进制字符串将保证它可以转换回二进制 double,而不会丢失任何数据。

换句话说,如果将每个可能的双精度值转换为 17 位数字的十进制字符串(正确舍入),它们将全部映射到不同的值。因此不存在数据丢失。


不过,我不确定单精度的最小截止值。但我怀疑它会是 8 或 9 位数字。

According to this page:

Actually, the IEEE754-1985 standard says that 17 decimal digits is
enough in all cases. However, it seems that the standard is a little
vague on whether conforming implementations must guarantee lossless
conversion when 17 digits are used.

So storing a double as a decimal string with at least 17 digits (correctly rounded) will guarantee that it can be converted back to binary double 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.

丢了幸福的猪 2025-01-04 14:45:47

鉴于 IEEE 格式只能表示有限数量的(二进制)数字,因此具有最低精度(参见 epsilon),因此您只需要有限数量的(十进制)数字。当然,如果实现(strtodsnprintf)在{所有浮点数}和{每个浮点数一个十进制表示}集合之间具有恒等映射行为,那就更好了。

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}.

驱逐舰岛风号 2025-01-04 14:45:47

在 java 中,可以通过构造中间 BigDecimal 对象将 double 转换为字符串:

double doubleValue = ...;

// From double to string
String valueOfDoubleAsString = new BigDecimal(doubleValue).toString();
// And back
double doubleValueFromString = new BigDecimal(valueOfDoubleAsString).doubleValue();

// doubleValue == doubleValueFromString

此方法不存在区域设置问题。
但是,特殊的双精度值(Infinite、NaN)当然不起作用。

In java, it is possible to convert double from/to string, by constructing an intermediate BigDecimal object:

double doubleValue = ...;

// From double to string
String valueOfDoubleAsString = new BigDecimal(doubleValue).toString();
// And back
double doubleValueFromString = new BigDecimal(valueOfDoubleAsString).doubleValue();

// doubleValue == doubleValueFromString

There is no locale issue with this method.
However, special double values (Infinite, NaN) will of course not work.

深海少女心 2025-01-04 14:45:47

在 C 中,printf 有一个标志 a,它将写入 IEEE 双精度数的精确表示,如

double f;
printf("%a", f);

这在手册页中记录。可以使用 scanf 读取结果。

在 python 中,您可以使用其中任何一个

s = '%a' % f
s = ascii(f)
s = repr(f)

来保证打印可以转换回原始浮点数的表示形式

s = '%a' % f
assert f == float(s)

In C, there is a flag a to the printf that will write an exact representation of IEEE doubles, as in

double f;
printf("%a", f);

This is documented in the man page. The result can be read with scanf.

In python , you can use any of

s = '%a' % f
s = ascii(f)
s = repr(f)

this is guaranteed to print a representation that can be cast back to the original float

s = '%a' % f
assert f == float(s)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文