简体   繁体   English

浮点数错误的解决方法是什么?

[英]what is the workaround for floating point inacurracy?

Here's the code snippet: 这是代码片段:

float pNum = 9.2;
char* l_tmpCh = new char[255];

sprintf_s(l_tmpCh, 255, "%.9f", pNum);

cout << l_tmpCh << endl;

delete l_tmpCh;

the output is: 9.199999809 输出为: 9.199999809
What to do in order for the result to be 9.200000000 为了使结果为9.200000000,该怎么办
Note: I need every float number printed with 9 decimals precision, so I don't want to have 9.2 注意:我需要以9位小数精度打印每个浮点数,所以我不想设置9.2

The workaround is to not use floating point numbers.. 解决方法是不使用浮点数。

Not every number can be represented accurately in the floating point format, such as, for example, 9.2. 并非每个数字都能以浮点格式(例如9.2)准确表示。 Or 0.1. 或0.1。

If you want all the decimals shown, then you get 9.199999809 , because that's floating point value closest to 9.2. 如果要显示所有小数,则得到9.199999809 ,因为那是最接近9.2的浮点值。

If you use floating point numbers you have to accept this inaccuracy. 如果使用浮点数,则必须接受这种不准确性。 Otherwise, your only option is to store the number in another format. 否则,您唯一的选择是以其他格式存储号码。

Required reading 必读

There is no way a 32-bit binary float number have 9 digits of precision ( there is only 7 ). 32位二进制浮点数不可能有9位精度( 只有7位 )。 You could fake it by appending 3 zeroes. 您可以通过添加3个零来伪造它。

sprintf_s(l_tmpCh, 255, "%.6f000", pNum);

This won't work if the integer part exhausted a lot of precision already, eg 9222.2f will give 9222.200195000 . 如果整数部分已经用尽了很多精度,这将不起作用,例如9222.2f将给出9222.200195000

What you're asking for is not possible in the general case since floating point numbers by definiton are approximations, which might or might not have an exact representation in decimal. 在一般情况下,您所要求的是不可能的,因为按定义的浮点数是近似值,它可能会或可能不会以十进制形式精确表示。 Read the famous Goldberg paper: http://docs.sun.com/source/806-3568/ncg_goldberg.html 阅读著名的Goldberg论文: http : //docs.sun.com/source/806-3568/ncg_goldberg.html

Use a double literal rather than a float literal. 使用双精度文字而不是浮点文字。

double pNum = 9.2;
char* l_tmpCh = new char[255];

sprintf_s(l_tmpCh, 255, "%.9f", pNum);

cout << l_tmpCh << endl;

delete l_tmpCh;

That f was making the literal a float; f使字面量浮起来; without it, the value is a double literal (more precise at about 15 decimal digits). 如果没有它,则该值为双字面量(更精确的约15个十进制数字)。

Of course, if 15 digits isn't enough, you're welcome to create your own class to represent values. 当然,如果15位数字不够用,欢迎您创建自己的类来表示值。

This should do it: 应该这样做:

double pNum = 9.2;

The f suffix makes it a float literal, which has only about 7 decimal digits of precision and of course suffers from representation errors . 后缀f使其成为float文字,其精度只有大约7个十进制数字,并且当然存在表示错误 Assigning it to a double variable does not fix this. 将其分配给double变量不能解决此问题。 Of course, this assumes that float and double correspond to IEEE 754 single and double precision types. 当然,这假定floatdouble对应于IEEE 754单精度和双精度类型。

EDIT: If you want to use float , then this problem cannot be solved at all. 编辑:如果您想使用float ,那么这个问题根本无法解决。 Read The Floating-Point Guide to understand why. 阅读《浮点指南》以了解原因。

It's important to understand that native floating point numbers are seldom "accurate" because of the way they are represented in the computer. 重要的是要了解,由于本机浮点数在计算机中的表示方式很少“准确”。 Thus most of the time you only get an approximation. 因此,大多数时候您只能得到一个近似值。 And with printf, you also specify the precision with which to round that approximation to an output. 使用printf,还可以指定将近似值四舍五入到输出的精度。 Eg "%.20f" will give you a representation that is rounded to 20 digits after the "." 例如,“%。20f”将为您提供一个在“之后”四舍五入至20位数字的表示形式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM