C# 将 double 转换为 float 是否总是返回相同的值?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9743044/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 08:40:09  来源:igfitidea点击:

Does casting double to float always return same value?

c#floating-pointdoublerounding

提问by

Does casting doubleto floatalways produce same result, or can there be some "rounding differences"?

难道铸造doublefloat总是产生相同的结果,也可以有一些“整差异”?

For example, is xin

例如,x

float x = (float)0.123456789d;

always the same value?

总是相同的值?

What about when casting float to double, and then casting it back to float ie. (float)(double)someFloat?

当将浮动转换为双倍,然后将其转换回浮动时会怎样,即。(float)(double)someFloat?

Mostly interested in what the results are in C#, but feel free to share if you have knowledge about how this works on other languages.

主要对 C# 中的结果感兴趣,但如果您了解它在其他语言上的工作原理,请随时分享。

采纳答案by phoog

The results should not be language dependent, unless the language deviates from the IEEE specification.

结果不应依赖于语言,除非语言偏离 IEEE 规范。

All floats can be exactly represented as doubles, so the round trip from float to double to float should yield the same value that you started with.

所有浮点数都可以精确地表示为双精度数,因此从浮点数到双精度数再到浮点数的往返应该产生与您开始时相同的值。

Similarly, casting any double value to float should always yield the same result, but, of course, there are many different double values that would truncate to the same float value.

类似地,将任何 double 值转换为 float 应该总是产生相同的结果,但是,当然,有许多不同的 double 值会被截断为相同的 float 值。

回答by Kendall Frey

A double should be able to to exactly hold every possible value of a float. Casting a float to a double should not change the value, and casting back to a float should return the original value, as long as you didn't perform any calculations on the double in the meantime.

double 应该能够准确地保存浮点数的每个可能值。将 float 转换为 double 不应更改该值,而转换回 float 应返回原始值,只要您在此期间未对 double 执行任何计算。

回答by Tigran

Considering that they have different precision, even i you're casting from less precision to wider one (I suppose that is actually your doubt) the result can not be alwaysthe same.

考虑到它们具有不同的精度,即使您从较低的精度转换为较宽的精度(我想这实际上是您的疑问),结果也不能总是相同的。

Floating point operations, especially casting, are always a subject of truncating/rounding and any other type of approximation.

浮点运算,尤其是强制转换,始终是截断/舍入和任何其他类型近似的主题

回答by Ethan Brown

Floating-point numbers in C# are stored using the IEEE 754 format (http://en.wikipedia.org/wiki/IEEE_754). This format has two parts: the digits and the exponent. Doubles hold 52 digits, and floats hold 23 digits. The base is 2, not ten. So for your example above (0.123456789), the digits would be 111010110111100110100010101 (the binary representation of 123456789). That's 27 digits, which fits comfortably in a double, but not in a float, so yes, precision would be lost in the round-trip conversion.

C# 中的浮点数使用 IEEE 754 格式 (http://en.wikipedia.org/wiki/IEEE_754) 存储。这种格式有两部分:数字和指数。双打52位数,浮点数23位数。基数是 2,而不是 10。因此,对于上面的示例 (0.123456789),数字将是 111010110111100110100010101(123456789 的二进制表示)。那是 27 位数字,可以轻松地放入双精度数中,但不能放入浮点数中,所以是的,往返转换中会丢失精度。

On the other hand, if your number was 0.123456, the digits would be 11110001001000000 (17 digits) which fits comfortably in either a float or a decimal, so you would lose no precision in a round-trip cast.

另一方面,如果您的数字是 0.123456,则数字将是 11110001001000000(17 位),这很适合浮点数或小数,因此您在往返转换中不会失去精度。

回答by Nicholas Carey

If you downcasta doubleto a float, you are losing precision and data. Upcasting a floatto a doubleis a wideningconversion; no data is lost if it is then round-tripped...that is, unless you do somethingto the value prior to downcasting it back to a float.

如果你垂头丧气doublefloat,你失去的精度和数据。float将 a向上转换为 adouble是一种扩大转换;如果然后往返,则不会丢失任何数据......也就是说,除非您在将其向下转换回浮点数之前对该值进行某些操作

Floating-point numbers sacrifice precision and accuracy for range. Single-precision floats give you 32-bits of precision; double-precision give you 64-bits. But they can represent values way outside the bounds that the underlying precision would indicate.

浮点数牺牲了range 的精度和准确度。单精度浮点数为您提供 32 位精度;双精度给你 64 位。但是它们可以表示超出潜在精度所指示范围的值。

C# floatand doubleare IEEE 754 floating point values.

C#floatdoubleIEEE 754 浮点值。

The effective precision of the mantissa is 1-bit more than its apparent size (floating point magick).

尾数的有效精度比其表观大小(浮点魔法)多 1 位。

Some CLR floating point resources for you:

一些 CLR 浮点资源供您使用:

This paper is probably the canonical paper on the perils and pitfalls of floating point arithmetic. If you're not a member of the ACM, click the link on the title to find public downloads of the article:

这篇论文可能是关于浮点运算的危险和陷阱的规范论文。如果您不是 ACM 的成员,请单击标题上的链接以查找文章的公共下载:

  • David Goldberg. 1991. What every computer scientist should know about floating-point arithmetic. ACM Comput. Surv. 23, 1 (March 1991), 5-48. DOI=10.1145/103162.103163 http://doi.acm.org/10.1145/103162.103163

    Abstract
    Floating-point arithmetic is considered as esoteric subject by many people. This is rather surprising, because floating-point is ubiquitous in computer systems: Almost every language has a floating-point datatype; computers from PCs to supercomputers have floating-point accelerators; most compilers will be called upon to compile floating-point algorithms from time to time; and virtually every operating system must respond to floating-point exceptions such as overflow. This paper presents a tutorial on the aspects of floating-point that have a direct impact on designers of computer systems. It begins with background on floating-point representation and rounding error, continues with a discussion of the IEEE floating point standard, and concludes with examples of how computer system builders can better support floating point.

  • 大卫·戈德堡。1991.每个计算机科学家都应该了解的关于浮点运算的知识。ACM 计算。生存。23, 1 (1991 年 3 月), 5-48。DOI=10.1145/103162.103163 http://doi.acm.org/10.1145/103162.103163

    抽象的
    许多人认为浮点运算是一门深奥的学科。这相当令人惊讶,因为浮点在计算机系统中无处不在:几乎每种语言都有浮点数据类型;从个人电脑到超级计算机的计算机都有浮点加速器;大多数编译器会不时被要求编译浮点算法;几乎每个操作系统都必须响应浮点异常,例如溢出。本文介绍了对计算机系统设计人员有直接影响的浮点数方面的教程。它从浮点表示和舍入误差的背景开始,继续讨论 IEEE 浮点标准,并以计算机系统构建者如何更好地支持浮点的示例结束。

回答by supercat

In some cases, the closest floatrepresentation to a numeric quantity may differ from the value obtained by rounding the closest doublerepresentation to a float. Two such quantities are 12,344,321.4999999991 and 12,345,678.50000000093. The integers above and below both those quantities are precisely representable as float, but the nearest doubleto each of them has a fractional part of precisely 0.5. Because converting such doublevalues (between 2^23 and 2^24, with a fraction of precisely 0.5) to floatwill round to the nearest even integer; the compiler will in each case end up rounding away from the value which would have been closer to the original number.

在某些情况下,与float数值最接近的表示可能与通过将最接近的double表示四舍五入为 a获得的值不同float。两个这样的数量是 12,344,321.4999999991 和 12,345,678.50000000093。这两个量之上和之下的整数可以精确地表示为float,但最接近double它们的整数的小数部分恰好为 0.5。因为将这些double值(在 2^23 和 2^24 之间,精确到 0.5 的分数)转换为float将四舍五入到最接近的偶数;在每种情况下,编译器最终都会舍入远离更接近原始数字的值。

Note that in practice, the compiler seems to parse numbers as double, and then convert to float, so even though 12344321.4999999991f should round to 12344321f, it instead rounds to 12344322f. Likewise 12345678.50000000093f should rounds to 12345679f but rounds to 12345678f, so even in cases where conversion to doubleand then floatloses precision, such conversion loss cannot be avoided by specifying numbers directly as float.

请注意,在实践中,编译器似乎将数字解析为double,然后转换为float,因此即使 12344321.4999999991f 应舍入为 12344321f,它也会舍入为 12344322f。同样,12345678.50000000093f 应该舍入到 12345679f 但舍入到 12345678f,因此即使在转换为double然后float丢失精度的情况下,通过直接将数字指定为 也无法避免这种转换损失float

Incidentally, the values 12344321.4999999992f and 12345678.50000000094f are rounded correctly.

顺便提一下,值 12344321.4999999992f 和 12345678.50000000094f 被正确舍入。