Skip to content

BitConverter: ToDouble, ToSingle, Int64BitsToDouble, Int32BitsToDouble #2977

Open

Description

@peteroupc

Link to article:
https://docs.microsoft.com/en-us/dotnet/api/system.bitconverter.todouble?view=netstandard-2.0

Problem:

Mention that it might not be possible to use these methods to produce what are so-called signaling NaNs in x86, x64, and certain other instruction set architectures. A signaling NaN is an NaN with the most significant bit of the mantissa area clear (as opposed to a quiet NaN where that bit is set). An example of a signaling NaN is as follows (with little-endian byte ordering):

new byte[]{ 1, 0, 0, 0, 0, 0, 0xf0, 0x7f };

At least in x86, using ToDouble and converting the resulting double back will convert the signaling NaN to a quiet NaN as follows:

new byte[]{ 1, 0, 0, 0, 0, 0, 0xf8, 0x7f };

This can be an issue if the application works with binary serialization formats that store double or float values in the form of the bits that make them up, because converting those bits to double or float with these BitConverter methods may make round-tripping that double or float not always possible.

Activity

  1. added
    untriagedNew issue has not been triaged by the area owner
    on Aug 11, 2019
  2. added
    Pri3Indicates issues/PRs that are low priority
    on Nov 11, 2020
  3. eiriktsarpalis commented on Feb 26, 2021

    @eiriktsarpalis
    Member

    Tagging @pgovind @tannergooding for triage.

  4. tannergooding commented on Feb 26, 2021

    @tannergooding
    Member

    Thanks! This repros on .NET Core using:

    var xb = new byte[] { 1, 0, 0, 0, 0, 0, 0xf0, 0x7f };
    var yb = new byte[] { 1, 0, 0, 0, 0, 0, 0xf8, 0x7f };
    
    var x = BitConverter.ToDouble(xb);
    var y = BitConverter.ToDouble(yb);
    
    Console.WriteLine(Environment.Is64BitProcess);
    Console.WriteLine($"{x}    {BitConverter.DoubleToInt64Bits(x):X16}");
    Console.WriteLine($"{y}    {BitConverter.DoubleToInt64Bits(y):X16}");

    I'd like to investigate a bit more and determine "why" the value is being changed (I expect it might be due to the x87 FPU stack).

  5. peteroupc commented on Jun 30, 2021

    @peteroupc
    Author

    Another curiosity I found with respect to NaN.

    In .NET, Double.NaN and Single.NaN have the following bit patterns:

    new byte[]{ 0, 0, 0, 0, 0, 0, 0, 0xff }
    new byte[]{ 0, 0, c0, ff }
    

    Where the so-called "sign bit" of the value (topmost bit of the last byte) is set. Whereas in Java, for example, the equivalent Double.NaN and Float.NaN have that bit clear:

    new byte[]{ 0, 0, 0, 0, 0, 0, 0, 0x7f }
    new byte[]{ 0, 0, c0, 7f }
    

    This shows once again the multi-faced nature of NaN.

    Related: WebAssembly/interface-types#134

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Pri3Indicates issues/PRs that are low priorityarea-System.RuntimeuntriagedNew issue has not been triaged by the area owner

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions