给定一个实值,我们可以检查float数据类型是否足以存储数字,或者需要double数据类型吗?
我知道不同建筑的精确度各不相同。是否有任何C/C++函数来确定正确的数据类型?
- 两者都可以从负无穷大存储到正无穷大。
- 是的,可能是浮动还是双浮动,或者两者都不够!
- @你一定在开玩笑…
- @pubby:en.wikipedia.org/wiki/computable_编号
- "足够"是什么意思?您的意思是在最小和最大浮点值的范围内吗?或者一个浮点数是否能精确地表示它?
- 没有这样的C++函数。您有责任确定所需的精度。在此基础上,选择浮点或双值的表示。
- @ JakobS。Pubby是正确的。范围是从负无穷大到正无穷大。
- @约翰巴塞洛缪:不是。除了负无穷大和正无穷大本身有一个表示外,当然在数字上有一个巨大的差距,对于任何有限的表示,应该如何没有。可表示数的范围类似于10^-45..10^38,用于float,例如。
- @ JakobS。这个间隙与范围无关,它只是意味着在无穷大和相应的最大数量有限数之间没有可表示的值,就像两个相邻的可表示的有限值之间没有可表示的值一样。
- @约翰·巴塞洛缪——有时候最好简单地提供一个到可靠来源的链接——en.wikipedia.org/wiki/…
- @Schepurin:当然,浮点格式有一个最大的可表示的有限数(两个,如果同时包含正和负的话),当然,这些数和最近的无穷大之间有很大的差距。但是浮点格式可以同时表示正无穷大和负无穷大,因此它们的范围从负无穷大扩展到正无穷大。你不同意其中的哪一部分?
- @约翰巴塞洛缪:好的,同意;)
- @约翰·巴塞洛缪——现在没问题了。但是,像这样的问题(解释而不是解决方案)几乎总是可以用链接的源信息更好地回答。
- @谢普林:是的。我完全同意。
有关背景,请参阅每个计算机科学家应该了解的关于浮点运算的知识。
不幸的是,我认为没有任何方法可以使决策自动化。
通常,当人们用浮点数而不是字符串来表示数字时,目的是使用数字进行算术运算。即使所有输入都符合给定的浮点类型,并且精度可以接受,您仍然需要考虑舍入误差和中间结果。
在实践中,大多数计算都将使用64位类型,具有足够的精度来获得可用的结果。许多计算只使用32位就无法得到可用的结果。
在现代处理器中,总线和算术单元的宽度足以提供32位和64位浮点类似的性能。使用32位的主要动机是在存储非常大的数组时节省空间。
这将导致以下策略:
如果数组足够大,足以证明花费大量精力将其大小减半是合理的,那么请进行分析和实验,以确定32位类型是否能提供足够好的结果,如果是这样,请使用它。否则,请使用64位类型。
- 矢量计算(例如SSE)通过使用单精度和双精度的同一个ALU可能获得两倍的吞吐量,因此64位ALU是常见的不是一个好理由。同样,无论总线的宽度如何,您都可以在相同的时间内通过数据总线容纳两倍多的32位数字。让事情变小的动机是表现。不管怎样,对精度的某种分析通常是有必要的,因为没有这种分析,64位的精度错误和32位的精度错误可能会使您蒙蔽。
我认为你的问题预设了一种在没有精确损失的情况下向C/C++(或任何其他程序)指定任何"实数"的方法。
假设您通过在代码中指定或通过用户输入获得这个实数;一种检查float或double是否足以在不丢失精度的情况下存储它的方法是只计算有效位的数量,并对照float和double的数据范围检查它。
如果数字是以表达式(即1/7或sqrt(2)给出的),您还需要检测:
- 如果数字是有理数,那么它是有重复小数还是循环小数。
- 或者,当你有一个无理数时会发生什么?
此外,还有一些数字,比如0.9,在理论上,float/double不能"精确地"表示,至少在我们的二进制计算范式中不能如此——请看jon skeet关于这一点的最佳答案。
最后,请参阅关于浮动与双精度的其他讨论。
精度与平台无关。虽然平台允许不同,但float几乎是通用的IEEE标准单精度,double是双精度。
单精度在基数点(小数点)后指定23位尾数或二进制数字。因为点之前的位总是1,这等于24位小数。除以log2(10)=3.3,浮点数得到精度的7.2位小数。
按照相同的过程,double生成16.2位数字,long double生成19.2位数字(对于Intel和大多数使用80位格式的系统)。
尾数之外的位用于指数。指数位数决定了允许的数字范围。单程至~10±38,双程至~10±308。
至于您是否需要7、16或19位数字,或者如果有限的精度表示法完全合适,那就超出了问题的范围。这取决于算法和应用程序。
一篇非常详细的文章,可以回答你的问题,也可以不回答你的问题。
浮点数复杂的整个系列!
- 嗯,我读了系列文章中关于浮点复杂度的前十几项,它们充其量过于简单化,最坏的情况是完全错误的。例如,"flt_min不是最小的正浮点数(flt_min是最小的正标准化浮点数)"如果硬件执行次标准化,则为真。大多数是,但不是全部。这就是为什么std::numeric_limits有一个名为has_denorm的布尔成员。
- 这篇特别的文章确实说明了它正在讨论的是IEEE754标准,其中定义了子规范。如果您的硬件恰好不符合标准,那么您就很难指责一篇关于标准的文章在硬件方面是错误的。文章可能过于简单化,但对于不了解整个浮点业务的人来说,我觉得它的复杂性是正确的。
- 我只看了第一页,但不知道它在哪里说的是关于IEEE754的。无论如何,C++不需要IEEE 754。大多数人对浮点运算的问题是,他们对浮点运算的看法过于简单化;然而,另一个过于简单化却没有帮助。
- @对于绝大多数程序员来说,假设他们的编程平台为他们提供了IEEE754浮点运算,并且理解这意味着什么(在altdevblogaday.com/2012/04/05/floating-point-completities上列出的一些含义),这将是一个巨大的改进。
- @当然,如果它清楚地表明所说的内容适用于IEEE754的实现。我对所讨论的文章的反对意见是,它提供了可爱的概括性,而没有提供上下文。
你不能简单地把它存储到一个float和一个double变量中,然后比较这两个变量吗?这应该隐含地将float转换回双精度-如果没有差别,float就足够了?
1 2 3 4 5 6
| float f = value;
double d = value;
if ((double)f == d)
{
// float is sufficient
} |
- 请不要像这样提出解决方案。float和double在很多方面都不同。
- @舍普林关心阐述"多方面"是什么?
- @安吉-我把它留给你研究。但你可以自由地反对这一点。
- 如果将double强制转换为float,然后再转换为double,则结果几乎为(*)永远不等于原始值,即使原始值可以表示为float(达到其精度)。
- @维克多:你的意思是,如果原始值可以表示为浮点,那么转换为浮点,再转换为双精度,几乎不会产生原始值?如果double中的值可以精确地表示为一个浮点值,那么两个转换都会产生精确的值;没有变化。
- @Eric Postischil-注意问题是关于精确性。处理浮点和双表示值,您可能需要考虑不同的格式,如STD::SETTAKEY。
- @谢普林:那句话似乎与我的问题无关。
- @埃里克·博士后-同意:)这是一个扭曲的讨论。只是想提供一个不实现这个解决方案的原因。
- @埃里克:这正是我想的。在所有其他情况下,我会说:float是不够的,因为这个数字不完全可以表示为float,因此"某物"丢失了。你是否关心这个"东西"必须由开发人员决定,而不是由机器决定。
- @Eric Postischil double有53位的有效位,float有24位的有效位,当您将double转换为float时,即使数字在单精度float的最小/最大值范围内,也会丢失29位(我没有说它是否可以精确表示,我想这是我的错误选择)。
- @维克多:这个答案中的代码用于检测double是否可以准确地表示为float。考虑到这一点,您所描述的行为不是批评;它支持代码的目的:不能由float精确表示的double由往返转换更改,而可以由float精确表示的double则不更改。这就是目的。
- 好吧,我同意它准确地回答了这个问题。我发现这个问题…值得怀疑的。OP想要解决的问题是什么?
不能用浮点或双变量表示实数,只能用有理数的子集。
当您进行浮点计算时,您的CPU浮点单元将为您决定最佳近似值。
我可能错了,但我认为float(4字节)和double(8字节)浮点表示实际上是独立于comp架构指定的。