为什么我不能乘以浮点数?

发布于 2024-09-05 15:22:41 字数 404 浏览 8 评论 0原文

可能的重复:
处理浮点数的精度问题

惊讶为什么我尝试在 C 中乘以浮点数(使用 GCC 3.2),但它没有按我的预期进行。作为示例:

int main() {
  float nb = 3.11f;
  nb *= 10;
  printf("%f\n", nb);
}

显示:31.099998

我很好奇浮点数的实现方式以及为什么它会产生这种意外的行为?

Possible Duplicate:
Dealing with accuracy problems in floating-point numbers

I was quite surprised why I tried to multiply a float in C (with GCC 3.2) and that it did not do as I expected.. As a sample:

int main() {
  float nb = 3.11f;
  nb *= 10;
  printf("%f\n", nb);
}

Displays: 31.099998

I am curious regarding the way floats are implemented and why it produces this unexpected behavior?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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

发布评论

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

评论(6

猫弦 2024-09-12 15:22:41

首先,您可以乘以浮点数。你遇到的问题不是乘法本身,而是你使用的原始数字。乘法可能会损失一些精度,但在这里,您相乘的原始数字一开始就损失了精度。

这实际上是预期的行为。 float 使用二进制表示形式实现,这意味着它们无法准确表示十进制值。

有关详细信息,请参阅 MSDN

您还可以在 float 的说明中查看它具有 6-7 位有效数字的精度。在您的示例中,如果将 31.099998 舍入为 7 位有效数字,您将得到 31.1,因此它仍然按预期工作。

double 类型当然会更准确,但由于它是二进制表示形式,而您写入的数字是十进制,因此仍然存在舍入误差。

如果您希望十进制数字完全准确,则应使用十进制类型。这种类型存在于 C# 等语言中。 http://msdn.microsoft.com/en-us/library/system .decimal.aspx

您还可以使用有理数表示。只要您可以将数字表示为两个整数的除法,使用两个整数就可以提供完全的准确性。

First off, you can multiply floats. The problem you have is not the multiplication itself, but the original number you've used. Multiplication can lose some precision, but here the original number you've multiplied started with lost precision.

This is actually an expected behavior. floats are implemented using binary representation which means they can't accurately represent decimal values.

See MSDN for more information.

You can also see in the description of float that it has 6-7 significant digits accuracy. In your example if you round 31.099998 to 7 significant digits you will get 31.1 so it still works as expected here.

double type would of course be more accurate, but still has rounding error due to it's binary representation while the number you wrote is decimal.

If you want complete accuracy for decimal numbers, you should use a decimal type. This type exists in languages like C#. http://msdn.microsoft.com/en-us/library/system.decimal.aspx

You can also use rational numbers representation. Using two integers which will give you complete accuracy as long as you can represent the number as a division of two integers.

心奴独伤 2024-09-12 15:22:41

这按预期工作。计算机的精度是有限的,因为它们试图从整数计算浮点值。这会导致浮点不准确。

浮点维基百科页面比我可以在这里:)

有趣的现实世界旁注:这个这就是为什么很多金钱计算都是使用整数(美分)完成的部分原因 - 不要让计算机因缺乏精度而损失金钱!我想要我的 0.00001 美元!

This is working as expected. Computers have finite precision, because they're trying to compute floating point values from integers. This leads to floating point inaccuracies.

The Floating point wikipedia page goes into far more detail on the representation and resulting accuracy problems than I could here :)

Interesting real-world side-note: this is partly why a lot of money calculations are done using integers (cents) - don't let the computer lose money with lack of precision! I want my $0.00001!

梦纸 2024-09-12 15:22:41

数字 3.11 不能用二进制表示。 24 位有效位最接近的值为 11.0001110000101000111101,十进制结果为 3.1099998950958251953125。

如果您的数字 3.11 应该代表货币金额,那么您需要使用十进制表示形式。

The number 3.11 cannot be represented in binary. The closest you can get with 24 significant bits is 11.0001110000101000111101, which works out to 3.1099998950958251953125 in decimal.

If your number 3.11 is supposed to represent a monetary amount, then you need to use a decimal representation.

爱,才寂寞 2024-09-12 15:22:41

在Python社区中,我们经常看到人们对此感到惊讶,因此有经过充分测试和调试的常见问题解答教程部分问题(当然,它们是用Python而不是C语言来表达的,但由于Python无论如何都将浮点算术委托给底层C和硬件,所以浮点机制的所有描述仍然适用)。

当然,这不是乘法的错——删除乘法 nb 的语句,无论如何你都会看到类似的问题。

In the Python communities we often see people surprised at this, so there are well-tested-and-debugged FAQs and tutorial sections on the issue (of course they're phrased in terms of Python, not C, but since Python delegates float arithmetic to the underlying C and hardware anyway, all the descriptions of float's mechanics still apply).

It's not the multiplication's fault, of course -- remove the statement where you multiply nb and you'll see similar issues anyway.

孤独患者 2024-09-12 15:22:41

来自维基百科文章

浮点数的事实
不能准确代表所有真实的
数字,以及浮点数
运算不能精确表示
真正的算术运算,导致
许多令人惊讶的情况。这是
与有限精度相关
计算机一般代表哪些
数字。

From Wikipedia article:

The fact that floating-point numbers
cannot precisely represent all real
numbers, and that floating-point
operations cannot precisely represent
true arithmetic operations, leads to
many surprising situations. This is
related to the finite precision with
which computers generally represent
numbers.

橘味果▽酱 2024-09-12 15:22:41

浮点不精确,因为它们使用基数 2(因为它是二进制:0 或 1)而不是基数 10。并且正如许多人之前所说,基数 2 转换为基数 10 将导致舍入精度问题。

Floating points are not precise because they use base 2 (because it's binary: either 0 or 1) instead of base 10. And base 2 converting to base 10, as many have stated before, will cause rounding precision issues.

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