简体   繁体   English

浮点数不准确?

[英]Floating point numbers inaccuracy?

I am prompting the user to input a float number. 我提示用户输入一个浮点数。 I save the number in float variable and multiply it by 100 to make it integer. 我将数字保存在float变量中,然后乘以100以使其为整数。 Only 2 decimal places are allowed so it is a fairly easy thing. 只允许小数点后2位,所以这很容易。 Now the strange part : 现在奇怪的部分是:

  1. User Input : 0.1 -> Output : 100 用户输入:0.1->输出:100
  2. User Input : 1.1 -> Output : 110 用户输入:1.1->输出:110
  3. User Input : 1.5 -> Output : 150 用户输入:1.5->输出:150
  4. User Input : 2.1 -> Output : 209.999985 用户输入:2.1->输出:209.999985
  5. User Input : 2.5 -> Output : 250 用户输入:2.5->输出:250
  6. User Input : 3.8 -> Output : 380 用户输入:3.8->输出:380
  7. User Input : 4.2 -> Output : 419.999969 用户输入:4.2->输出:419.999969
  8. User Input : 5.6 -> Output : 560 用户输入:5.6->输出:560
  9. User Input : 6.0 -> Output : 600 用户输入:6.0->输出:600
  10. User Input : 7.5 -> Output : 750 用户输入:7.5->输出:750
  11. User Input : 8.1 -> Output : 810.000061 用户输入:8.1->输出:810.000061
  12. User Input : 9.9 -> Output : 989.999969 用户输入:9.9->输出:989.999969

I tried this thing only till 10.00. 我只尝试了这件事直到10.00。

Referring Why Are Floating Point Numbers Inaccurate? 请问为什么浮点数不正确? I got to know the reason behind this behavior, but isn't there any way to know which number would behave strangely? 我知道了此行为的原因,但是没有任何办法知道哪个数字的行为会奇怪吗?

I don't know of a way to predict which numbers will do this, but most programmers don't really care. 我不知道一种预测哪个数字将执行此操作的方法,但是大多数程序员并不在乎。

You didn't specify the language you are using, but if you want to change something from a floating point representation into an integer representation, you usually have to do an explicit conversion using a function like Double.intValue() or Double.longValue() in Java or a cast operator (int)double_value; 您没有指定使用的语言,但是如果要将某些内容从浮点表示形式更改为整数表示形式,通常必须使用Double.intValue()Double.longValue() Double.intValue()类的函数进行显式转换。 Double.longValue()或Java转换运算符(int)double_value;

These techniques usually just cast off the fractional part of the number. 这些技术通常只是剔除数字的小数部分。 You may want to use a rounding function instead. 您可能要使用舍入函数。 Again, in java that would be Math.round() as described in the [javadoc] ( http://docs.oracle.com/javase/7/docs/api/java/lang/Math.html ) 再次,在Java中,如[javadoc]( http://docs.oracle.com/javase/7/docs/api/java/lang/Math.html )中所述,它将为Math.round() )。

I can only tell you with which numbers this will not happen: 我只能告诉您不会发生哪些数字:
With all numbers that can be represented exactly in binary, that is all numbers of the form: 所有可以精确地用二进制表示的数字,即形式为所有数字:

N = Sum(i, 2^n(i))

or: 要么:

N = 2^n1 + 2^n2 + 2^n3 + ....

where n(i) are integers (positive or negative) from a limited range. 其中n(i)是有限范围内的整数(正数或负数)。

Use FLT_DIG to print numbers within their matching decimal notation. 使用FLT_DIG以匹配的十进制符号形式打印数字。

FLT_DIG to the number of leading decimal digits that a float will display and match its decimal assigned value. FLT_DIGfloat将显示的前导十进制数字的数目,并与其十进制分配的值匹配。 It is at least 6. In the below example, 2.1 can be printed to 2.10000e+00 which is 6 significant digits. 至少为 6。在下面的示例中,可以将2.1打印到2.10000e+00 ,这是6个有效数字。 990.0 can be printed to 9.90000e+02 which is also 6 significant digits. 可以将990.0打印到9.90000e+02 ,这也是6位有效数字。

printf("%.*e", FLT_DIG - 1, 2.1f);  // 2.10000e+00
printf("%.*e", FLT_DIG - 1, 990.f); // 9.90000e+02

When code does operations like multiplying by 100 , the float product may incur a round-off error. 当代码执行诸如乘以100操作时, float乘积可能会产生舍入误差。 C does not specify accuracy here, but an error of < 0.5 parts in 16 million can be expected. C在这里没有指定精度,但是可以预期<0.5百万分之一的误差。 With many operations, this eats into the number of reliable digits down from FLT_DIG . 通过许多操作,这会减少从FLT_DIG到可靠数字的数量。

In general, avoid expecting matching arithmetic and computer results finer than FLT_DIG digits. 通常,避免期望匹配算法和计算机结果比FLT_DIG数字更好。 If that is insufficient, use double , which is is at least good for at least 10 digits (and with typical double , is good for 15 digits - use DBL_DIG ) 如果那还不够,请使用double ,它至少对至少10位数字有效(对于典型的double ,对15位数字有利-使用DBL_DIG

Note: "%.5e" direct printf() to print 1 digit before and 5 digits after the decimal point for a total of 6 significant digits. 注意: "%.5e"指示printf()在小数点前打印1位,在小数点后打印5位,总共6位有效数字。 That is the reason for -1 in printf("%.*e", FLT_DIG - 1, ...); 这就是在printf("%.*e", FLT_DIG - 1, ...);-1的原因printf("%.*e", FLT_DIG - 1, ...);

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

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