-6

I'm putting together a small handful of extension methods, for converting numeric values to their binary equivalents.

But I'm running into a problem.

We may use a Convert.ToString() overload to convert these types to binary:

Byte
Short
Integer
Long

For example:

Dim iInteger As Integer
Dim sBinary As String

iInteger = Integer.MaxValue
sBinary = Convert.ToString(iInteger, 2)

But there isn't an overload for Single that accepts the base value. The single-argument overload returns scientific notation, not the binary value.

I've tried this code, adapted from this answer:

Public Function ToBinary(Value As Single) As String
  Dim aBits As Integer()

  Dim _
    iLength,
    iIndex As Integer

  Select Case Value
    Case < BitLengths.BYTE : iLength = 7
    Case < BitLengths.WORD : iLength = 15
    Case < BitLengths.DWORD : iLength = 31
    Case < BitLengths.QWORD : iLength = 63
  End Select

  aBits = New Integer(iLength) {}

  For iIndex = 0 To iLength
    aBits(iLength - iIndex) = Value Mod 2
    Value \= 2
  Next

  ToBinary = String.Empty

  aBits.ForEach(Sub(Bit)
                  ToBinary &= Bit
                End Sub)
End Function

Unfortunately, however, it returns inaccurate results:

Input: 1361294667
Result: Assert.AreEqual failed. Expected:<01010001001000111011010101001011>. Actual:<01010001001000111011010110000000>.

We can get the expected value from the Programmer View of the old Windows 7 calculator:

Enter image description here

Given these, how may we reliably convert a Single value to a binary string?

--EDIT--

I found this statement: "There is not an exact binary representation of 0.1 or 0.01." That pretty much says it all. I've decided to abandon this, as it's become clear that the effort is a fruitless pursuit.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
InteXX
  • 6,135
  • 6
  • 43
  • 80
  • 4
    Is this *BASIC*? Whichever language it is, please tag your post with it. – Ross Jacobs Sep 21 '19 at 03:02
  • @RossJacobs ~ It's language-agnostic (at least as far as the .NET Framework is concerned). It doesn't matter to me the language in which the answer comes, so if I tag it as VB.NET I'll be sharply restricting the avenue for a successful answer. That said, I will add the .NET tag. Thank you for the suggestion. – InteXX Sep 21 '19 at 05:44
  • 5
    It is quite unclear what an "accurate result" is supposed to look like. Single is a floating point number, its binary representation looks [like this](https://en.wikipedia.org/wiki/Single-precision_floating-point_format#IEEE_754_single-precision_binary_floating-point_format:_binary32). Note the bits dedicated to sign, mantissa and exponent. You can dump them into a string of 32 ones and zeros, but that string means very little. The code snippet focuses on the value only, that very quickly becomes impractical. Take 1E38, takes 127 bits of which only the first 24 have a non-random value. – Hans Passant Sep 21 '19 at 07:10
  • 3
    So representing the value is a no-go. Getting to the bits is hard to do in vb.net and you need to use a casting trick to map from Single to Integer. Check [this post](https://stackoverflow.com/questions/4654227/overriding-gethashcode-in-vb-without-checked-unchecked-keyword-support/4656890#4656890) for the Caster struct. – Hans Passant Sep 21 '19 at 07:13
  • @HansPassant ~ Hans, you've given me some good meat to chew on here. This is going to take me a bit. But I'll get back to you once I've had a chance to do so. In the meantime I'll edit my post to clarify what the inaccuracies are that I encountered. Thanks for that suggestion. – InteXX Sep 21 '19 at 07:15
  • 4
    this question is [discussed at meta](https://meta.stackoverflow.com/q/389642/839601) – gnat Sep 21 '19 at 08:59
  • 4
    ... [twice](https://meta.stackoverflow.com/q/389648). – Zoe Sep 21 '19 at 11:48
  • Of interest: RosettaCode: [Binary digits](http://rosettacode.org/wiki/Binary_digits) – Guy Coder Sep 21 '19 at 17:21
  • @GuyCoder ~ Hm, interesting. The .NET Framework versions won't work, as they encounter the same overload problem as I've discussed here, but I might be able to port the Visual FoxPro code. I'll give it a try. Thanks, good resource. – InteXX Sep 21 '19 at 18:12
  • @HansPassant ~ I found [this statement](https://husobee.github.io/money/float/2016/09/23/never-use-floats-for-currency.html): *"There is not an exact binary representation of 0.1 or 0.01."* That pretty much says it all. I've decided once and for all to abandon this, as it's become clear that the effort is a fruitless pursuit. Thanks for helping me arrive at this conclusion. – InteXX Sep 22 '19 at 18:08

1 Answers1

7

The example expected value you've provided is just a straight binary representation of the number, however while probably not the most efficient way if you wanted to get the IEEE-754 representation of the number in binary you could use BitConverter.GetBytes as in the following example:

Sub Main
    Dim i As Int32 = 1361294667
    Console.WriteLine(ObjectAsBinary(i))
    Dim s As Single = 1361294667
    Console.WriteLine(ObjectAsBinary(s))
End Sub

Private Function ObjectAsBinary(o As Object) As String
    Dim bytes = BitConverter.GetBytes(o)
    If BitConverter.IsLittleEndian Then
        Array.Reverse(bytes)
    End If
    Dim result As String = ""
    For Each b In bytes
        result &= Convert.ToString(b, 2).PadLeft(8, "0")
    Next
    Return result
End Function

That code outputs the following:

01010001001000111011010101001011 - Matches your example

01001110101000100100011101101011 - Matches IEEE-754 from IEEE-754 Floating Point Converter

PeterJ
  • 3,705
  • 28
  • 51
  • 71
  • I'm not sure I understand. Why are the two results different, when their starting values are the same? – InteXX Sep 21 '19 at 10:17
  • @InteXX the first one is a straight binary number representation for an integer, for single floating point it's a bit more complex and the binary will look like this: https://en.wikipedia.org/wiki/Single-precision_floating-point_format#IEEE_754_single-precision_binary_floating-point_format:_binary32 – PeterJ Sep 21 '19 at 10:36
  • I found [this statement](https://husobee.github.io/money/float/2016/09/23/never-use-floats-for-currency.html): *"There is not an exact binary representation of 0.1 or 0.01."* That pretty much says it all. I've decided to abandon this, as it's becoming clear that the effort is a fruitless pursuit. – InteXX Sep 22 '19 at 18:02