如何在Qt中打印带有所有小数的双精度?

时间:2016-03-05 11:52:14

标签: c++ qt double precision

首先,这不重复。我在网上搜索但没有答案就足够了。

我想打印一张双。所以我必须将它转换为QString。我想没有科学的符号和0.1应该打印0.1和1/3应该打印0.33333 ...双倍能够表示。不幸的是,我只能找到具有固定精度的解决方案,这导致上限为0.333333(在指定的p松动精度之后结束)或不必要的零填充0.100000。

我知道我可以最大限度地提高精度并丢弃所有尾随零,但不是一个很好的解决方案,它只打印最大可能但最小必要的精度?

编辑:我想我需要澄清一些事情。这个问题不是要将实数的空间映射成单个,双精度或任何精确的浮点数。它是关于逆:64位双精度浮点空间到我们心爱的真实世界实数的映射。由于前者是后者的一个子集,理论上这样做绝对没有问题。

2 个答案:

答案 0 :(得分:4)

尝试最简单的事情QString::number(1.0/3.0, 'g', 17);或使用std::ostream时,std::setprecision用于控制operator<<

的小数位数

答案 1 :(得分:1)

问题

与此处的其他评论和答案相反,这是一个非常合理的要求,问题似乎很清楚。浮点转换为字符串通常应该具有问题中描述的属性,而不是C和C ++标准库中的原始形式。您不应该指定精度,因为算法应该使用必要的。要扩展一点,请说你选择固定精度为6.然后你打印三个没有科学记数法的64位浮点数(最接近的那些)0.1,1.0 / 3.0和1.0 / 3000.0:

0.1

这里有几个问题。使用0.1时,最后会打印出不必要的零。打印0.10000000000000001 0.33333333333333331 0.00333333333333333 更加清晰,准确。使用其他数字,该值已被截断。 64位浮点数可以代表15个十进制数字,但我们只打印6.如果将字符串转换回浮点数,则不会获得相同的值。因此,让我们选择17的精度:

0.1

现在我们更好地代表1.0 / 3.0的值,但0.1只看起来更糟。打印QString::number会更准确,看起来更好。此外,我们仍然截断1.0 / 3000.0。您可以选择没有固定的精度来使数字打印得很好。

解决方案

有一个旧的,有点慢的算法(Dragon)来解决这个问题:

http://www.cs.indiana.edu/~dyb/pubs/FP-Printing-PLDI96.pdf

并且有一个更快的算法,Grisu,在2010年发布,但它需要回归到像Dragon这样的算法,占0.5%的浮点数:

http://dl.acm.org/citation.cfm?doid=1809028.1806623

有几种语言实现采用Grisu来打印浮点数(例如Firefox和Chrome的JS引擎以及Rust的标准库)。还有一种刚刚在2016年发布的算法,Errol,它改进了Grisu并且不需要回归Dragon。它是如此新颖,可能还没有看到任何采用:

http://dl.acm.org/citation.cfm?id=2837654

我今天需要良好的浮点打印,所以我一直在尝试使用Qt,而Qt似乎无法做出问题的要求。 QString::argQVariant{floatValue}.toString()都使用了较差的算法。

在Qt 5.7新功能列表中,有一个注释:

  

添加了将浮点转换为最短,精确字符串形式的功能,而无需预先计算多少位数; QVariant使用此

在我的测试中,使用{{1}}似乎符合要求,除了仍然使用非常小和大数字的科学记数法。这是Grisu算法的发明者的C ++库,看起来很棒(并且它允许选择何时使用科学记数法):

https://github.com/google/double-conversion