java中的浮点生成意外输出

java中的浮点生成意外输出,java,Java,我正在编写一个带有浮动的示例程序,但突然发生了一些奇怪的事情。如果有人能从我的程序中解释为什么我会面临这样的行为,我将不胜感激 package Programs; public class FloatTest { /** * @param args */ public static void main(String[] args) { float f1 = (float) 3.2; float f2 = (float) 6.

我正在编写一个带有浮动的示例程序,但突然发生了一些奇怪的事情。如果有人能从我的程序中解释为什么我会面临这样的行为,我将不胜感激

package Programs;

public class FloatTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        float f1 = (float) 3.2;
        float f2 = (float) 6.5;
        if (f1 == 3.2) {
            System.out.println(f1 + " same");
        } else {
            System.out.println(f1 + " different");
        }
        if (f2 == 6.5) {
            System.out.println(f2 + " same");
        } else {
            System.out.println(f2 + " different");
        }
    }
}
输出:

3.2 different
6.5 same
在做了一些改变f2值的测试之后,我注意到我得到了f2>3.5的意外结果,这是为什么?任何意见都非常感谢


谢谢

有很多方法可以绕过这个问题

发生此问题的原因是无法表示十进制值 在二进制中准确地显示

  • 有一个公差值,并检查差值是否小于公差值
  • 乘以10/100/。。。然后比较数字
  • 调查
  • 再看一看

    :)啊,IEEE754和JVM与浮点的区别。简言之,6.5与6.5的浮动值不同。6.5==6.5f将起作用,但您更好地了解自己在做什么!请阅读,并注意跨平台强制IEEE754行为的“strictfp”关键字。这里有很多事情要考虑,舍入行为,命令的顺序,JVM的差异等等。 您正在处理一个数字的二进制表示,该数字的精度适合于许多类型的数学计算,其中不需要非常精确的答案。对于许多工程和金融系统,尤其是涉及乘法或分数的系统,这是不可接受的。您需要重新设置会计基础(使用理解货币和小数的金融类)(例如,为货币计算便士),对于工程,您可能需要使用BigDecimal或具有特定舍入行为、感知等的相关类


    再举一个例子,1/3+1/3+1/3的浮点值可能等于或不等于1。因为构成数据的数字表示的1和0并不完全是1/3。在我的特定平台(JVM 1.6 Windows 64位)上,它是1.0,但可能不在您的平台上。

    由于浮点变量的表示方式,并非所有数字都可以精确表示。事实上,很少有人能做到

    当你写作时

    float f1 = (float) 3.2;
    
    将其与3.2进行比较,您将
    f1
    (a
    float
    )与
    3.2
    (a
    double
    3.2
    作为文本输入,隐式表示
    double
    类型)。在您的语句中,
    f1==3.2
    f1
    被隐式转换为
    double
    ,但此时,精度已丢失。这是因为
    3.2
    是无法精确表示的数字之一,而
    double
    float
    更能体现这一点


    巧合的是,
    6.5
    是其中一个数字(
    double
    float
    ),由于Java用于表示浮点的内部模式,可以精确地表示。这就是为什么,在你的例子中,
    f2==6.5
    真的

    我要尝试一下对此的技术解释。由于这些值最终以二进制格式存储,因此在某些情况下会丢失精度

    6.5
    不应丢失任何精度,因为它可以转换为二进制值
    110.1

    然而,
    3.2
    不能像这样干净地转换,因为
    .2
    的二进制表示变得不合理。这将是类似于
    11.00110011..
    的东西。这最多只能在以另一种方式转换时四舍五入到
    3.2


    如果有人能验证我所说的,那将是非常棒的——这是基于对Java如何处理这个问题的公认的有限知识

    虽然这看起来不太正确,但当你跑步时

    float f1 = (float) 3.2;
    
    f1
    实际上并不等于3.2。如前所述,有几种方法可以解决这个问题。

    使用cast
    如果(f1==(float)3.2){
    那么它就可以工作

    3.2
    这样的文本是double类型的,您将float与double进行比较,这会导致此类事情发生

    正如@JNL所指出的那样

    出现此问题的原因是十进制值无法在二进制中准确表示


    double double。因为6.5可以用二进制浮点精确表示,与3.2不同。@LeeMeador Java中的规则是,当转换为浮点或double时,数字被舍入到可以表示的最接近的值,如果等距,则舍入到最低有效位为0的值。这适用于literals和铸造,因此对于3.2f,浮动值将是最接近3.2的值;对于(浮动)3.2,文字3.2表示最接近3.2的双精度浮点值,然后将结果转换为最接近该双精度的浮点值。这两个值通常会产生相同的浮点值,但也有一些罕见的角点情况不会。对于公差,请使用以下内容:
    if(Math.abs(3.2f-f1)>0.05f)…
    。当然,我们可以整天争论将其与.0.05或0.000001或其他值进行比较的值。对于您的代码,您可能知道有多接近。这里有要点,所以+1。干杯-据我所知,存储像3.2这样的精确值的唯一方法是使用一个类似于BigDecimal的类在另一个答案中提到。事实上,尽管在大多数科学的数字运算中,双精度是足够的。但你绝对不能用浮点来表示货币。@Bathsheba你可以用浮点来表示货币。如果你需要做一些事情,比如计算利息或评估库存,当有物品有价值时,它会驱使你喝酒部件少于1美分(美元)的lues[例如,对于