4

In this question, Bill The Lizard asks how to display the binary representation of a float or double.

What I'd like to know is, given a binary string of the appropriate length, how could I perform the reverse operation (in C#)? In other words, how do I turn a binary string into a float or double?

As a side note, are there any bit strings which would not result in a valid float or double?


EDIT: By binary string I mean a string of 0s and 1s.

So, my input will be a string like this:

01010101010101010101010101010101

and my output should be a floating point number. (Or, if there were 64 bits in the string, a double.)

Community
  • 1
  • 1
Tom Wright
  • 11,278
  • 15
  • 74
  • 148
  • Can you use pointers? Then you can just fill up the bit pattern appropriately. I can give you a C answer if that helps. – Kerrek SB Nov 25 '11 at 17:59
  • 1
    You should be more specific about 'binary string' as no such thing exists. Do you mean a string with a hex representation? – H H Nov 25 '11 at 18:04
  • What do you mean by a binary string? A load of 0s and 1s, or some other representation? Could you give an example of expected input and output? – LukeH Nov 25 '11 at 18:05
  • @KerrekSB That seems like a long winded way of doing things, but thanks. – Tom Wright Nov 25 '11 at 18:05
  • @HenkHolterman Sorry, I assumed it was a well understood term. – Tom Wright Nov 25 '11 at 18:09

4 Answers4

6
double d1 = 1234.5678;
string ds = DoubleToBinaryString(d1);
double d2 = BinaryStringToDouble(ds);

float f1 = 654.321f;
string fs = SingleToBinaryString(f1);
float f2 = BinaryStringToSingle(fs);

// ...

public static string DoubleToBinaryString(double d)
{
    return Convert.ToString(BitConverter.DoubleToInt64Bits(d), 2);
}

public static double BinaryStringToDouble(string s)
{
    return BitConverter.Int64BitsToDouble(Convert.ToInt64(s, 2));
}

public static string SingleToBinaryString(float f)
{
    byte[] b = BitConverter.GetBytes(f);
    int i = BitConverter.ToInt32(b, 0);
    return Convert.ToString(i, 2);
}

public static float BinaryStringToSingle(string s)
{
    int i = Convert.ToInt32(s, 2);
    byte[] b = BitConverter.GetBytes(i);
    return BitConverter.ToSingle(b, 0);
}
LukeH
  • 263,068
  • 57
  • 365
  • 409
2
string bstr = "01010101010101010101010101010101";
long v = 0;
for (int i = bstr.Length - 1; i >= 0; i--) v = (v << 1) + (bstr[i] - '0');
double d = BitConverter.ToDouble(BitConverter.GetBytes(v), 0);
// d = 1.41466386031414E-314
MagnatLU
  • 5,967
  • 1
  • 22
  • 17
  • The guts of `BitConverter` are using pointers - here's Reflector'd body of `ToDouble`: `return *(((double*) &ToInt64(value, startIndex)));` – MagnatLU Nov 25 '11 at 18:04
  • 1
    That should come with a "don't do this at home" warning, as this is flat-out undefined behaviour in C. Presumably the C# implementation is relying on some assumptions about the compiler. – Kerrek SB Nov 25 '11 at 18:08
  • I don't think the string `aabbcc` is going to turn into a double in any meaningful way. – H H Nov 25 '11 at 18:08
  • 1
    @KerrekSB presumably the C# implementation is relying on the C# specification. – phoog Nov 25 '11 at 18:12
  • @phoog: What does the C# specification say about type punning and strict aliasing rules? – Kerrek SB Nov 25 '11 at 18:13
  • @HenkHolterman: it won't, but it's hard to tell what "binary string" meant before OPs edit. – MagnatLU Nov 25 '11 at 18:13
  • @KerrekSB it specifies the binary representation of `Int64` and of `double`, and it specifies rules for pointer conversions. – phoog Nov 25 '11 at 18:31
1

The same as in Marc's answer, you need BitConverter again:

Community
  • 1
  • 1
Vlad
  • 35,022
  • 6
  • 77
  • 199
0

Here's a solution that doesn't use BitConverter and isn't limited by the range of Int64.

static double BinaryStringToDouble(string s)
{
  if(string.IsNullOrEmpty(s))
    throw new ArgumentNullException("s");

  double sign = 1;
  int index = 1;
  if(s[0] == '-')
    sign = -1;
  else if(s[0] != '+')
    index = 0;

  double d = 0;
  for(int i = index; i < s.Length; i++)
  {
    char c = s[i];
    d *= 2;
    if(c == '1')
      d += 1;
    else if(c != '0')
      throw new FormatException();
  }

  return sign * d;
}

This version supports binary strings that represent values between to Double.MinValue and Double.MaxValue, or 1023 significant binary digits. It overflows to Double.PositiveInfinity or Double.NegativeInfinity.

@LukeH's answer only supports binary strings that represent values between to Int64.MinValue and Int64.MaxValue, or 63 significant binary digits.

Why you'd have a need for a binary string that is more than 63 digits in length is up for discussion.

If you don't want to allow a leading sign character, you can use this simpler version that only returns positive values.

static double BinaryStringToDouble(string s)
{
  if(string.IsNullOrEmpty(s))
    throw new ArgumentNullException("s");

  double d = 0;
  foreach(var c in s)
  {
    d *= 2;
    if(c == '1')
      d += 1;
    else if(c != '0')
      throw new FormatException();
  }

  return d;
}
Community
  • 1
  • 1
jordanbtucker
  • 5,768
  • 2
  • 30
  • 43