【问题标题】:Convert float to its binary representation (using MemoryStream?)将浮点数转换为其二进制表示(使用 MemoryStream?)
【发布时间】:2014-02-10 05:28:13
【问题描述】:

我想将给定的float 转换为其二进制表示。我尝试将浮点值写入MemoryStream,逐字节读取MemoryStream,并将字节转换为二进制表示。但每次尝试都失败了。

  • “无法读取已关闭的流”(但我只关闭了编写器)
  • 出于测试目的,我只是写了一个整数(我认为大小为四个字节),当我没有刷新 StreamWriter 时,MemoryStream 的长度为 0,当我刷新时为 1。李>

我确信有更好的方法将floats 转换为二进制,但我也想了解一下MemoryStream 类。

【问题讨论】:

    标签: c# binary memorystream floating-point-conversion


    【解决方案1】:

    您可以使用BitConverter.GetBytes(float) 或使用BinaryWriter 包装MemoryStream 并使用BinaryWriter.Write(float)。不清楚您之前对 MemoryStream 做了什么,但您不想想使用 StreamWriter - 那是文本。

    【讨论】:

    • 好的。我总是忘记,为特定目的使用哪个类 :) 感谢您的快速回答 :)
    • @Cubinator73:这就是文档的用途。例如,来自StreamWriter:“实现一个 TextWriter 以将字符写入特定编码的流”——这不是你想要的。
    • 是否有更有效的方法,例如将数据写入uint(对于float)和ulong(对于double)?使用byte[] 数组可能需要在堆上构造一个对象,并且不提供简单的按位操作。
    • @CommuSoft:doubleBitConverter.DoubleToInt64Bits 我不知道float 有类似的东西。
    • this page 上找到了一些东西。使用不安全指针进行转换:ulong db=*(ulong*)&d;uint fb=*(uint*)&f;。这可能是最有效的方式。
    【解决方案2】:

    使用 BitConverter,而不是 MemoryStream:

            // -7 produces "1 10000001 11000000000000000000000"
            static string FloatToBinary(float f)
            {
                StringBuilder sb = new StringBuilder();
                Byte[] ba = BitConverter.GetBytes(f);
                foreach (Byte b in ba)
                    for (int i = 0; i < 8; i++)
                    {
                        sb.Insert(0,((b>>i) & 1) == 1 ? "1" : "0");
                    }
                string s = sb.ToString();
                string r = s.Substring(0, 1) + " " + s.Substring(1, 8) + " " + s.Substring(9); //sign exponent mantissa
                return r;
            }
    

    【讨论】:

      【解决方案3】:

      Dotnetfiddle

      BitConverter.GetBytes(3.141f)
                  .Reverse()
                  .Select(x => Convert.ToString(x, 2))
                  .Select(x => x.PadLeft(8, '0'))
                  .Aggregate("0b", (a, b) => a + "_" + b);
      
      // res = "0b_01000000_01001001_00000110_00100101"
      

      无法抗拒使用“小型”LINQ 查询。 也适用于双精度。

      【讨论】:

        【解决方案4】:

        您在使用 StreamWriter 时可能遇到了一个陷阱,如下代码所示:

                // Write the float
                var f = 1.23456f;
                var ms = new MemoryStream();
                var writer = new StreamWriter(ms);
                writer.Write(f);
                writer.Flush();
        
                // Read 4 bytes to get the raw bytes (Ouch!)
                ms.Seek(0, SeekOrigin.Begin);
                var buffer = new char[4];
                var reader = new StreamReader(ms);
                reader.Read(buffer, 0, 4);
                for (int i = 0; i < 4; i++)
                {
                    Console.Write("{0:X2}", (int)buffer[i]);
                }
                Console.WriteLine();
        
                // This is what you actually read: human readable text
                for (int i = 0; i < buffer.Length; i++)
                {
                    Console.Write(buffer[i]);
                }
                Console.WriteLine();
        
                // This is what the float really looks like in memory.
                var bytes = BitConverter.GetBytes(f);
                for (int i = 0; i < bytes.Length; i++)
                {
                    Console.Write("{0:X2}", (int)bytes[i]);
                }
        
                Console.ReadLine();
        

        如果您希望流中只有 4 个字节并读取这 4 个字节,那么乍一看一切都很好。但实际上长度是 7,而您只读取了 float 文本表示的前 4 个字节。

        将其与 BitConverter 的输出进行比较,发现这里使用 StreamWriter 并不正确。

        【讨论】:

        • 最后三个字节是 BOM 吗?
        • 不,最后 3 个字节是数字 1.23456 的 456 个。前 4 个字节是数字 1.23456 的 1.23(包括点)。
        【解决方案5】:

        回答您的第一个问题:在 .Net 中,当您关闭/处置读取器/写入器时,底层流也会被关闭/处置。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-10-17
          • 1970-01-01
          • 2014-11-24
          • 2015-12-02
          • 2017-06-24
          • 2011-03-07
          • 2017-02-26
          相关资源
          最近更新 更多