Skip to content

The value of floatToRawIntBits(0.0f/0.0f) is different on x86_64 and aarch64 #11632

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
theopenlab-ci opened this issue Jul 15, 2019 · 9 comments

Comments

@theopenlab-ci
Copy link

The value of floatToRawIntBits(0.0f/0.0f) is different on x86_64 and aarch64:

on x86_64

root@donotdel-openlab-allinone-l00242678:/home/ubuntu# uname -a
Linux donotdel-openlab-allinone-l00242678 4.4.0-154-generic #181-Ubuntu SMP Tue Jun 25 05:29:03 UTC
2019 x86_64 x86_64 x86_64 GNU/Linux
scala> import java.lang.Float.floatToRawIntBits
import java.lang.Float.floatToRawIntBits
scala> floatToRawIntBits(0.0f/0.0f)
res0: Int = -4194304
scala> floatToRawIntBits(Float.NaN)
res1: Int = 2143289344

on aarch64

[root@arm-huangtianhua spark]# uname -a
Linux arm-huangtianhua 4.14.0-49.el7a.aarch64 #1 SMP Tue Apr 10 17:22:26 UTC 2018 aarch64 aarch64 aarch64 GNU/Linux
scala> import java.lang.Float.floatToRawIntBits
import java.lang.Float.floatToRawIntBits
scala> floatToRawIntBits(0.0f/0.0f)
res1: Int = 2143289344
scala> floatToRawIntBits(Float.NaN)
res2: Int = 2143289344

I test it using java, and the results are same on x86_64 and aarch64, so why scala has different values between these two platforms?

@huangtianhua
Copy link

Sorry, missed the info: Scala version 2.12.8

@huangtianhua
Copy link

@dwijnand Would you confirm this? Thank you.

@Jasper-M
Copy link

I'm confused. The bytecode is the same but the result is different.

scala> class A { def foo = Float.NaN; def bar = java.lang.Float.floatToRawIntBits(foo) }
defined class A

scala> class B { def foo = 0f / 0f; def bar = java.lang.Float.floatToRawIntBits(foo) }
defined class B

scala> new A().bar
res41: Int = 2143289344

scala> new B().bar
res42: Int = -4194304

scala> :javap  -c -filter A
Compiled from "<console>"
public class A {
  public float foo();
    Code:
       0: ldc           #16                 // float NaNf
       2: freturn

  public int bar();
    Code:
       0: aload_0
       1: invokevirtual #22                 // Method foo:()F
       4: invokestatic  #28                 // Method java/lang/Float.floatToRawIntBits:(F)I
       7: ireturn

  public A();
    Code:
       0: aload_0
       1: invokespecial #32                 // Method java/lang/Object."<init>":()V
       4: return
}

scala> :javap  -c -filter B
Compiled from "<console>"
public class B {
  public float foo();
    Code:
       0: ldc           #16                 // float NaNf
       2: freturn

  public int bar();
    Code:
       0: aload_0
       1: invokevirtual #22                 // Method foo:()F
       4: invokestatic  #28                 // Method java/lang/Float.floatToRawIntBits:(F)I
       7: ireturn

  public B();
    Code:
       0: aload_0
       1: invokespecial #32                 // Method java/lang/Object."<init>":()V
       4: return
}

@huangtianhua
Copy link

huangtianhua commented Jul 15, 2019

Using java on the two platforms, the results are same:

on aarch64

public class javaTest
{
public static void main(String[] args)
{
System.out.println(java.lang.Float.floatToRawIntBits(0.0f/0.0f));
System.out.println(java.lang.Float.floatToRawIntBits(Float.NaN));
System.out.println(0.0 / 0.0);
}
}
[root@arm-huangtianhua javaTest]# java javaTest
2143289344
2143289344
NaN

on x86_64

root@donotdel-openlab-allinone-l00242678:/hth/javaTest# vi javaTest.java
public class javaTest
{
public static void main(String[] args)
{
System.out.println(java.lang.Float.floatToRawIntBits(0.0f/0.0f));
System.out.println(java.lang.Float.floatToRawIntBits(Float.NaN));
System.out.println(0.0 / 0.0);
}
}
root@donotdel-openlab-allinone-l00242678:
/hth/javaTest# java javaTest
2143289344
2143289344
NaN

@plokhotnyuk
Copy link

plokhotnyuk commented Jul 15, 2019

NaN values can have different binary representations:

$ scala
Welcome to Scala 2.12.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_212).
Type in expressions for evaluation. Or try :help.

scala> java.lang.Float.isNaN(Float.NaN)
res0: Boolean = true

scala> java.lang.Float.isNaN(0.0f/0.0f)
res1: Boolean = true

@huangtianhua
Copy link

My question is why the behaviour is different on x86_64 and aarch64 platforms for java.lang.Float.floatToRawIntBits(0.0f/0.0f)?

@eed3si9n
Copy link
Member

https://en.wikipedia.org/wiki/IEEE_754-1985#NaN

sign = either 0 or 1.
biased exponent = all 1 bits.
fraction = anything except all 0 bits (since all 0 bits represents infinity).

Float has 1 bit of sign-bit and 23 bits for fraction, I think there are like 16777215 ways of representing NaN or something like that. I recently read something about someone stuffing information in that space.

@SethTisue
Copy link
Member

SethTisue commented Jul 15, 2019

closing on the assumption this is a JVM thing and not a Scala thing per se

it's not impossible there's some bug here, but in order to reopen, someone would need to demonstrate that there is a bug in Scala and not just a result that surprised you. otherwise what you have is just a question, not a bug report. questions should go on https://users.scala-lang.org, come here once you've become reasonably certain there is a bug in Scala itself

@huangtianhua
Copy link

@SethTisue OK, I will open a topic to https://users.scala-lang.org to discuss this, thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants