印刷浮,保持精度(printing float, preserving precision)

2019-06-25 05:09发布

我写印刷另一程序内使用浮点文字的程序。

多少位,我需要为了保留原有的浮法的精度打印?

由于浮体具有24 * (log(2) / log(10)) = 7.2247199的精度十进制数字,我的初始想法是,打印8个位数应该足够了。 但是,如果我不走运,那些0.2247199获得分配到左边和的7显著位的权利,所以我也许应该打印9个十进制数字。

是我的分析是正确的? 是9个十进制数字足以让所有的情况? 像printf("%.9g", x);

是否有转换的浮动与用于该值所需的小数的最小位数的字符串,在7或8足够的情况下,一个标准的功能,所以我不打印不必要的数字?

注:我不能使用十六进制浮点文字,因为标准C ++不支持他们。

Answer 1:

为了保证一个二进制> 10进制>二进制往返恢复原始二进制值, IEEE 754要求


The original binary value will be preserved by converting to decimal and back again using:[10]

    5 decimal digits for binary16
    9 decimal digits for binary32
    17 decimal digits for binary64
    36 decimal digits for binary128

For other binary formats the required number of decimal digits is

    1 + ceiling(p*log10(2)) 

where p is the number of significant bits in the binary format, e.g. 24 bits for binary32.

在C语言中,你可以使用这些转换的功能的snprintf()和strtof / strtod转换/ strtold()。

当然,在某些情况下甚至更多的数字可能是有用的(不,他们并不总是“噪音”,这取决于十进制转换例程,如snprintf的实行())。 考虑如打印向量分数 。



Answer 2:

24 *(日志(2)/日志(10))= 7.2247199

这对这个问题非常有代表性。 这是没有任何意义表达的显著的位数与0.0000001数字的准确性。 您正在转换的数字为文本的 ,不是机器的好处。 一种人一点也不在乎,并会更喜欢,如果你写

24 *(日志(2)/日志(10))= 7

试图显示8位显著刚刚产生的随机噪声数字。 非零几率7已经很深了,因为浮点错误计算累积。 首先,印刷用数字衡量的合理单元。 人们感兴趣的是毫米,克,斤,英寸,等等。 没有建筑师会在意一个窗口的大小大于1mm更准确地表达。 无窗的制造工厂将保证尺寸精确为一个窗口。

最后但并非最不重要的,你不能忽视你喂到你的程序的数字的准确性。 测量空载欧洲燕子的速度降低到7个数字是不可能的。 这充其量是每秒约11米,2位数字。 所以对速度进行计算和打印有更多显著数字的结果产生承诺的准确性,是不是有无意义的结果。



Answer 3:

如果程序是指由计算机阅读,我会做使用的简单的一招char*走样。

  • 别名float*char*
  • 复制到一个unsigned (或任何无符号类型是足够大的),通过char*混叠
  • 打印unsigned价值

解码只是在倒车过程中(以及大多数平台有直接reinterpret_cast可以使用)。



Answer 4:

如果您有符合C99 C库(如果你的浮点类型有一个基础,是2的幂:)的printf格式字符%a可打印浮点值,而不缺乏精确的十六进制形式,和公用事业scanfstrod将能够阅读。



Answer 5:

浮点到十进制在Java中使用的转换是保证产生的十进制数字数最少超过区分其邻居(或多或少)的数目所需要的小数点。

您可以将算法从这里复制: http://www.docjar.com/html/api/sun/misc/FloatingDecimal.java.html注意FloatingDecimal(float)构造函数和toJavaFormatString()方法。



Answer 6:

如果你读这些文件(见下文),你会发现,有一些算法打印的十进制数字,使得数可以重新诠释不变(由scanf函数IE)的最小数量。

因为可能有几个这样的数字,该算法还挑最近的小数原来的二进制小数(我命名为浮点值)。

比较可惜的是有一个在C.没有这样的标准库

  • http://www.cs.indiana.edu/~burger/FP-Printing-PLDI96.pdf
  • http://grouper.ieee.org/groups/754/email/pdfq3pavhBfih.pdf


Answer 7:

您可以使用sprintf 。 我不知道这是否回答你的问题虽然准确,但不管怎么说,这里是示例代码

#include <stdio.h>
int main( void )
{
float d_n = 123.45;
char s_cp[13] = { '\0' };
char s_cnp[4] = { '\0' };
/*
* with sprintf you need to make sure there's enough space
* declared in the array
*/
sprintf( s_cp, "%.2f", d_n );
printf( "%s\n", s_cp );
/*
* snprinft allows to control how much is read into array.
* it might have portable issues if you are not using C99
*/
snprintf( s_cnp, sizeof s_cnp - 1 , "%f", d_n );
printf( "%s\n", s_cnp );
getchar();
return 0;
}
/* output :
* 123.45
* 123
*/


Answer 8:

喜欢的东西

def f(a):
    b=0
    while a != int(a): a*=2; b+=1
    return a, b

(这是Python的),你应该能够得到尾数和指数的无损耗的方式。

在C语言中,这很可能是

struct float_decomp {
    float mantissa;
    int exponent;
}

struct float_decomp decomp(float x)
{
    struct float_decomp ret = { .mantissa = x, .exponent = 0};
    while x != floor(x) {
        ret.mantissa *= 2;
        ret.exponent += 1;
    }
    return ret;
}

但要注意,仍然不是所有的值可以以这种方式来表示,这仅仅是一个快速射击应该给这个想法,但可能需要改进。



文章来源: printing float, preserving precision