Float vs Double

时间:2012-04-10 04:16:16

标签: java c floating-point

如果您将两个浮点值之间的比较(equals())与false进行比较,则会返回DOUBLE,如果您进行比较,则会返回true他们是FLOAT?

我正在编写一些程序,作为我的小组项目的一部分,来比较任何给定类型的两个数值。我必须处理4种类型:doublefloatintlong。所以我想将doublefloat分组到一个函数中,也就是说,我只是将float投射到double并进行比较。

这会导致任何不正确的结果吗?

感谢。

7 个答案:

答案 0 :(得分:14)

如果您要将双精度转换为浮点数并且它们之间的差异超出浮点类型的精度,则可能会遇到麻烦。

例如,假设您有两个双重值:

9.876543210
9.876543211

并且浮点数的精度只有六位十进制数。这意味着两个float值都是9.87654,因此相等,即使双值本身不相等。

但是,如果你在谈论浮动被投射到双打,那么相同的浮动应该给你相同的双打。如果浮标不同,额外的精度将确保双打也是不同的。

答案 1 :(得分:9)

只要你没有在你的比较中混合推广的花车和原生计算的双打,你应该没问题,但要小心:

比较花车(或双打)是否难以平等 - see this lengthy but excellent discussion

以下是一些亮点:

  1. 由于浮点格式精度有限的问题,您无法使用==

  2. float(0.1)和double(0.1)分别是不同的值(0.100000001490116119384765625和0.1000000000000000055511151231257827021181583404541015625)。在你的情况下,这意味着比较两个浮点数(通过转换为double)可能没问题,但是如果你想比较一个浮点数和一个双精度数,请小心。

  3. 通常使用epsilon或小值进行相对比较(如果a - b < epsilon,则浮动a和b被视为相等)。在C中,float.h正是为了这个目的而定义FLT_EPSILON。但是,在ab非常小或非常大的情况下,此类比较不起作用。

  4. 你可以通过使用缩放相对于大小的a和b的epsilon来解决这个问题,但在某些情况下会出现这种情况(例如比较为零)。

  5. 您可以比较浮点数的integer representations,以找出它们之间有多少可表示的浮点数。这就是Java的Float.equals()所做的。这称为ULP差异,用于“最后位置的单位”差异。它通常很好,但在与零比较时也会崩溃。

  6. 文章的结论是:

      

    知道你在做什么

         

    没有银弹。你必须明智地选择。

         
        
    • 如果您要与零进行比较,那么相对epsilons和基于ULP的比较通常是没有意义的。您需要使用绝对epsilon,其值可能是FLT_EPSILON的一小部分和计算的输入。也许。
    •   
    • 如果您要与非零数字进行比较,那么基于相对epsilons或ULP的比较可能就是您想要的。你可能想要一些FLT_EPSILON的小倍数用于你的相对epsilon,或者一些少量的ULP。如果你确切知道你要比较的数字,可以使用绝对的epsilon。
    •   
    • 如果您要比较两个可能为零或非零的任意数字,那么您需要厨房水槽。祝你好运和上帝的速度。
    •   

    所以,回答你的问题:

    • 如果您要将double降级为float s,则可能会失去精确度,并错误地将两个不同的double报告为相同(paxdiablo指出。 )
    • 如果您要将相同的float升级为double,那么添加的精度将不会是的问题,除非您要将floatdouble进行比较float(假设您在浮点数上有1.234,并且您只有4位小数的精度,那么双1.2345 MIGHT表示与浮点数相同的值。在这种情况下,您可能更好地做以double的精度进行比较,或者更一般地,在比较中最不准确的表示的错误级别进行比较。
    • 如果您知道要与之比较的数字,可以按照上述建议进行操作。
    • 如果您要比较任意数字(可能是零或非零),则无法在所有情况下正确比较它们 - 选择一个比较并了解其局限性。

    一些实际的考虑因素(因为这听起来像是作业):

    • 大多数人提到的epsilon比较可能很好(但包括对写作中的限制的讨论)。如果您计划将双精度数与浮点数进行比较,请尝试在浮点数中进行,但如果没有,请尝试以双精度进行所有比较。更好的是,只需在任何地方使用{{1}}。

    • 如果您想完全改变作业,请在比较浮点数时列出问题的说明以及选择任何特定比较方法的理由。

答案 2 :(得分:2)

我不明白为什么你这样做。 ==运算符已经满足了双方所有可能的类型,并且已经在相关语言标准中指定了类型强制和扩展的广泛规则。你所要做的就是使用它。

答案 3 :(得分:2)

我可能没有回答OP的问题,而是回应了一些或多或少需要澄清的模糊建议。

绝对可以比较两个浮点值的相等性,并且可以完成。如果类型是单精度或双精度通常不太重要。

说过导致比较的步骤本身需要非常小心,并且需要彻底了解浮点数和注意事项,以及为什么不做。

考虑以下C语句:

result = a * b / c;
result = (a * b) / c;
result = a * (b / c);

在大多数天真的浮点编程中,它们被视为“等效”,从而产生“相同”的结果。在浮点的现实世界中,他们可能是。或者实际上,前两个是等价的(因为第二个遵循C评估规则,即从左到右的相同优先级的运算符)。第三个可能或可能不等于第一个twp。

为什么会这样?

“a * b / c”或“b / c * a”可能导致“不精确”异常,即中间或最终结果(或两者)不精确(可以浮点格式表示) 。如果是这种情况,结果或多或少会略有不同。这可能会或可能不会导致最终结果适合于相等比较。意识到这一点,并且一次一步地进行操作 - 注意到中间结果 - 将允许患者程序员“击败系统”,为几乎任何情况构建高质量的浮点比较。

对于其他所有人来说,通过浮动数字的相等比较是好的,可靠的建议。

这真的有点讽刺,因为大多数程序员都知道整数数学会在各种情况下产生可预测的截断。说到浮点几乎每个人都或多或少地震惊,结果并不准确。去图。

答案 4 :(得分:1)

只要相等测试涉及delta,你就可以进行演员表。

例如:abs((double) floatVal1 - (double) floatVal2) < .000001应该有效。

编辑以回应问题更改

不,你不会。以上仍然有效。

答案 5 :(得分:1)

对于float f和double d之间的比较,可以计算f和d的差值。如果abs(f-d)小于某个阈值,你可以想到等式成立。根据您的应用要求,这些阈值可以是绝对的或相对的。有一些很好的解决方案Here。我希望它有所帮助。

答案 6 :(得分:0)

  

如果我推广2个花车,我会得到不正确的结果吗?   加倍并进行64位比较而不是32位比较?

没有

如果你从两个浮点开始,可能是浮点变量(float x = foo();)或浮点常量(1.234234234f),那么你可以直接比较它们。如果将它们转换为double然后进行比较,那么结果将是相同的。

这是因为double是一组超级浮点数。也就是说,可以存储在float中的每个值都可以存储在double中。指数和尾数的范围都增加了。有数十亿的值可以存储在double中但不能存储在float中,但是零值可以存储在float中但不能存储为double。

正如我在float comparison article中所讨论的那样,在float或double值之间进行有意义的比较可能会很棘手,因为舍入错误可能已经悄悄进入。但是,将这两个数字从float转换为double并不是没有改变这一点。所有提到的epsilons(通常但并不总是需要)与问题完全正交。

另一方面,comparing a float to a double is madness。 1.1(一个双精度型)不等于1.1f(一个浮点数),因为1.1中的1.1不能完全表示。