• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

C#通用的二进制转化为float和double方法

武飞扬头像
斯内科
帮助1

二进制转化float(double)方法:

            //单精度浮点数对应32位
            //符号位(Sign) : 0代表正,1代表为负【占1位】
            //指数位(Exponent):用于存储科学计数法中的指数数据,并且采用移位存储【占8位】
            //尾数部分(Mantissa):尾数部分【占23位】
            //单精度float:N共32位,其中S占1位,E占8位,M占23位。因此小数点后最多精确到23/4=6位 
            //双精度double:N共64位,其中S占1位,E占11位,M占52位。因此小数点后最多精确到52/4=13位 

            //IEEE规则:二进制32位转float【Real】规则
            //第一位为1代表负数,第一位为0代表正数或者0
            //第二位到第九位代表 指数位,对应的值减去127就是移位数【shiftCount】
            //【第十位开始】尾数23位前面加一个1,凑够24位,这个24位尾数的前【shiftCount 1】个数就是整数部分,剩下的就是小数部分

            //整数二进制转为10进制:从低位到高位分别是2的0次幂、1次幂、2次幂……,分别相乘再相加,得到的和即为10进制结果。
            //小数部分的二进制转换位10进制:与整数部分类似,从小数点开始分别是2的-1次幂、-2次幂、-3次幂……,分别相乘再相加,得到的和即为10进制结果,比如001(2进制)对应0.125(10进制)

目标数据类型 源二进制位数 转化逻辑
float(Real、Single) 32位

第一位为1代表负数,第一位为0代表正数或者0
第二位到第九位代表 指数位,对应的值减去127就是移位数【shiftCount】

第十位开始】尾数23位前面加一个1,凑够24位,这个24位尾数的前【shiftCount 1】个数就是整数部分,剩下的就是小数部分

double(LReal、Double) 64位

第一位为1代表负数,第一位为0代表正数或者0
第二位到第十二位代表 指数位,对应的值减去1023就是移位数【shiftCount】

第十三位开始】尾数52位前面加一个1,凑够53位,这个53位尾数的前【shiftCount 1】个数就是整数部分,剩下的就是小数部分

 C#源程序如下:

关键方法:static T BinaryBitToFractional<T>(byte[] binaryArraySource) where T : struct 

  1.  
    using System;
  2.  
    using System.Collections.Generic;
  3.  
    using System.Linq;
  4.  
    using System.Text;
  5.  
    using System.Threading.Tasks;
  6.  
     
  7.  
    namespace BinaryToFloatDemo
  8.  
    {
  9.  
    class Program
  10.  
    {
  11.  
    static void Main(string[] args)
  12.  
    {
  13.  
    Console.SetWindowSize(160, 50);
  14.  
    //单精度浮点数对应32位
  15.  
    //符号位(Sign) : 0代表正,1代表为负【占1位】
  16.  
    //指数位(Exponent):用于存储科学计数法中的指数数据,并且采用移位存储【占8位】
  17.  
    //尾数部分(Mantissa):尾数部分【占23位】
  18.  
    //单精度float:N共32位,其中S占1位,E占8位,M占23位。因此小数点后最多精确到23/4=6位
  19.  
    //双精度double:N共64位,其中S占1位,E占11位,M占52位。因此小数点后最多精确到52/4=13位
  20.  
     
  21.  
    //IEEE规则:二进制32位转float【Real】规则
  22.  
    //第一位为1代表负数,第一位为0代表正数或者0
  23.  
    //第二位到第九位代表 指数位,对应的值减去127就是移位数【shiftCount】
  24.  
    //【第十位开始】尾数23位前面加一个1,凑够24位,这个24位尾数的前【shiftCount 1】个数就是整数部分,剩下的就是小数部分
  25.  
     
  26.  
    //整数二进制转为10进制:从低位到高位分别是2的0次幂、1次幂、2次幂……,分别相乘再相加,得到的和即为10进制结果。
  27.  
    //小数部分的二进制转换位10进制:与整数部分类似,从小数点开始分别是2的-1次幂、-2次幂、-3次幂……,分别相乘再相加,得到的和即为10进制结果,比如001(2进制)对应0.125(10进制)
  28.  
    byte[] binary32ArraySource = new byte[4] { 80, 32, 241, 71 };
  29.  
    byte[] binary64ArraySource = new byte[8] { 215, 252, 96, 26, 153, 190, 60, 194 };
  30.  
    try
  31.  
    {
  32.  
    float fNumber = Binary32BitToFloat(binary32ArraySource);
  33.  
    Console.WriteLine(fNumber);
  34.  
     
  35.  
    double dNumber = Binary64BitToDouble(binary64ArraySource);
  36.  
    Console.WriteLine(dNumber);
  37.  
     
  38.  
    Console.WriteLine($"-------------下面整体测试通用方法【{nameof(BinaryBitToFractional)}】-------------");
  39.  
    fNumber = BinaryBitToFractional<float>(binary32ArraySource);
  40.  
    Console.WriteLine(fNumber);
  41.  
    dNumber = BinaryBitToFractional<double>(binary64ArraySource);
  42.  
    Console.WriteLine(dNumber);
  43.  
    }
  44.  
    catch (Exception ex)
  45.  
    {
  46.  
    Console.WriteLine(ex.Message);
  47.  
    }
  48.  
    Console.ReadLine();
  49.  
    }
  50.  
     
  51.  
    /// <summary>
  52.  
    /// 32位二进制转化为对应的浮点数float【Real】
  53.  
    /// </summary>
  54.  
    /// <param name="binaryArraySource"></param>
  55.  
    /// <returns></returns>
  56.  
    private static float Binary32BitToFloat(byte[] binaryArraySource)
  57.  
    {
  58.  
    if (binaryArraySource == null || binaryArraySource.Length != 4)
  59.  
    {
  60.  
    throw new ArgumentException($"源数组不能为空并且有且只有4个元素", nameof(binaryArraySource));
  61.  
    }
  62.  
    byte[] binaryArray = binaryArraySource.Reverse().ToArray();
  63.  
    Console.WriteLine($"将数组顺序反转,反转后为【{string.Join(",", binaryArray)}】");
  64.  
    IEnumerable<string> binaryCollection = binaryArray.Select(element => Convert.ToString(element, 2).PadLeft(8, '0'));
  65.  
    string binaryString = string.Join("", binaryCollection);
  66.  
    Console.WriteLine($"转化为32位二进制,为【{string.Join("\x20", binaryCollection)}】");
  67.  
    string signString = (binaryString[0] == '1' ? "-" : " ");
  68.  
    Console.WriteLine($"符号位占用1位,为【{signString}】");
  69.  
    string exponent = binaryString.Substring(1, 8);
  70.  
    int shiftCount = Convert.ToInt32(exponent, 2) - 127;
  71.  
    Console.WriteLine($"指数位为8位【{exponent}】,对应数字【{Convert.ToInt32(exponent, 2)}】,共移动【{shiftCount}】位");
  72.  
    string mantissa = binaryString.Substring(9);
  73.  
    string dotString = $"1.{mantissa}";
  74.  
    Console.WriteLine($"尾数位为23位【{mantissa}】,尾数位前面添加一个1并插入移位小数点,字符串为【{dotString}乘以2的{shiftCount}次方】");
  75.  
    dotString = dotString.Replace(".", "").Insert(shiftCount 1, ".");
  76.  
    Console.WriteLine($"即【{dotString}】");
  77.  
    string integerPart = dotString.Substring(0, shiftCount 1);//整数部分
  78.  
    string fractionalPart = dotString.Substring(shiftCount 2);//小数部分
  79.  
     
  80.  
    //整数部分:从低位到高位 依次是2的0次方,2个1次方,2的2次方,然后累加
  81.  
    long numberInteger = 0;
  82.  
    for (int i = 0; i < integerPart.Length; i )
  83.  
    {
  84.  
    if (integerPart[i] == '1')
  85.  
    {
  86.  
    numberInteger = (1L << (integerPart.Length - 1 - i));
  87.  
    }
  88.  
    }
  89.  
    //小数部分:从小数点开始分别是2的-1次幂、-2次幂、-3次幂……
  90.  
    decimal numberFractional = 0M;
  91.  
    for (int i = 0; i < fractionalPart.Length; i )
  92.  
    {
  93.  
    if (fractionalPart[i] == '1')
  94.  
    {
  95.  
    numberFractional = (decimal)Math.Pow(2, -1 - i);
  96.  
    }
  97.  
    }
  98.  
    Console.WriteLine($"整数部分【{integerPart}】,对应整数为【{numberInteger}】.或者使用Convert,整数也为【{Convert.ToInt32(integerPart, 2)}】");
  99.  
    Console.WriteLine($"小数部分【{fractionalPart}】,对应小数【{numberFractional}】");
  100.  
    string destNumber = $"{signString}{numberInteger numberFractional}";
  101.  
    Console.WriteLine($"32位二进制对应的浮点数为【{destNumber}】,使用BitConverter转换为浮点数的结果为【{BitConverter.ToSingle(binaryArraySource, 0)}】");
  102.  
    return float.Parse(destNumber);
  103.  
    }
  104.  
     
  105.  
    /// <summary>
  106.  
    /// 64位二进制转化为对应的双精度浮点数double【Double】
  107.  
    /// </summary>
  108.  
    /// <param name="binaryArraySource"></param>
  109.  
    /// <returns></returns>
  110.  
    private static double Binary64BitToDouble(byte[] binaryArraySource)
  111.  
    {
  112.  
    if (binaryArraySource == null || binaryArraySource.Length != 8)
  113.  
    {
  114.  
    throw new ArgumentException($"源数组不能为空并且有且只有8个元素", nameof(binaryArraySource));
  115.  
    }
  116.  
    byte[] binaryArray = binaryArraySource.Reverse().ToArray();
  117.  
    Console.WriteLine($"将数组顺序反转,反转后为【{string.Join(",", binaryArray)}】");
  118.  
    IEnumerable<string> binaryCollection = binaryArray.Select(element => Convert.ToString(element, 2).PadLeft(8, '0'));
  119.  
    string binaryString = string.Join("", binaryCollection);
  120.  
    Console.WriteLine($"转化为64位二进制,为【{string.Join("\x20", binaryCollection)}】");
  121.  
    string signString = (binaryString[0] == '1' ? "-" : " ");
  122.  
    Console.WriteLine($"符号位占用1位,为【{signString}】");
  123.  
    string exponent = binaryString.Substring(1, 11);
  124.  
    int shiftCount = Convert.ToInt32(exponent, 2) - 1023;
  125.  
    Console.WriteLine($"指数位为8位【{exponent}】,对应数字【{Convert.ToInt32(exponent, 2)}】,共移动【{shiftCount}】位");
  126.  
    string mantissa = binaryString.Substring(12);
  127.  
    string dotString = $"1.{mantissa}";
  128.  
    Console.WriteLine($"尾数位为52位【{mantissa}】,尾数位前面添加一个1并插入移位小数点,字符串为【{dotString}乘以2的{shiftCount}次方】");
  129.  
    dotString = dotString.Replace(".", "").Insert(shiftCount 1, ".");
  130.  
    Console.WriteLine($"即【{dotString}】");
  131.  
    string integerPart = dotString.Substring(0, shiftCount 1);//整数部分
  132.  
    string fractionalPart = dotString.Substring(shiftCount 2);//小数部分
  133.  
     
  134.  
    //整数部分:从低位到高位 依次是2的0次方,2个1次方,2的2次方,然后累加
  135.  
    long numberInteger = 0L;
  136.  
    for (int i = 0; i < integerPart.Length; i )
  137.  
    {
  138.  
    if (integerPart[i] == '1')
  139.  
    {
  140.  
    numberInteger = (1L << (integerPart.Length - 1 - i));
  141.  
    }
  142.  
    }
  143.  
    //小数部分:从小数点开始分别是2的-1次幂、-2次幂、-3次幂……
  144.  
    decimal numberFractional = 0M;
  145.  
    for (int i = 0; i < fractionalPart.Length; i )
  146.  
    {
  147.  
    if (fractionalPart[i] == '1')
  148.  
    {
  149.  
    numberFractional = (decimal)Math.Pow(2, -1 - i);
  150.  
    }
  151.  
    }
  152.  
    Console.WriteLine($"整数部分【{integerPart}】,对应整数为【{numberInteger}】.或者使用Convert,整数也为【{Convert.ToInt64(integerPart, 2)}】");
  153.  
    Console.WriteLine($"小数部分【{fractionalPart}】,对应小数【{numberFractional}】");
  154.  
    string destNumber = $"{signString}{numberInteger numberFractional}";
  155.  
    Console.WriteLine($"64位二进制对应的浮点数为【{destNumber}】,使用BitConverter转换为浮点数的结果为【{BitConverter.ToDouble(binaryArraySource, 0)}】");
  156.  
    return double.Parse(destNumber);
  157.  
    }
  158.  
     
  159.  
    /// <summary>
  160.  
    /// 通用的二进制32位或64位 转浮点小数
  161.  
    /// </summary>
  162.  
    /// <typeparam name="T">仅支持float和double</typeparam>
  163.  
    /// <param name="binaryArraySource"></param>
  164.  
    /// <returns></returns>
  165.  
    private static T BinaryBitToFractional<T>(byte[] binaryArraySource) where T : struct
  166.  
    {
  167.  
    if (typeof(T) != typeof(float) && typeof(T) != typeof(double))
  168.  
    {
  169.  
    throw new Exception($"类型错误,必须是浮点数类型【float或double】");
  170.  
    }
  171.  
    if (binaryArraySource == null)
  172.  
    {
  173.  
    throw new ArgumentException($"源数组不能为空", nameof(binaryArraySource));
  174.  
    }
  175.  
    if (typeof(T) == typeof(float) && binaryArraySource.Length != 4)
  176.  
    {
  177.  
    throw new ArgumentException($"转化为float时,源数组必须有且只有4个元素", nameof(binaryArraySource));
  178.  
    }
  179.  
    if (typeof(T) == typeof(double) && binaryArraySource.Length != 8)
  180.  
    {
  181.  
    throw new ArgumentException($"转化为double时,源数组必须有且只有8个元素", nameof(binaryArraySource));
  182.  
    }
  183.  
     
  184.  
    //单精度float:N共32位,其中S占1位,E占8位,M占23位。因此小数点后最多精确到23/4=6位
  185.  
    int signBitCount = 1;//符号位数,代表正数还是负数
  186.  
    int exponentBitCount = 8;//指数位数
  187.  
    int mantissaBitCount = 23;//尾数位数
  188.  
    int totalBitCount = 32;//二进制总位数
  189.  
    if (typeof(T) == typeof(double))
  190.  
    {
  191.  
    //双精度double:N共64位,其中S占1位,E占11位,M占52位。因此小数点后最多精确到52/4=13位
  192.  
    exponentBitCount = 11;//指数位数
  193.  
    mantissaBitCount = 52;//尾数位数
  194.  
    totalBitCount = 64;//二进制总位数
  195.  
    }
  196.  
    byte[] binaryArray = binaryArraySource.Reverse().ToArray();
  197.  
    Console.WriteLine($"将数组顺序反转,反转后为【{string.Join(",", binaryArray)}】");
  198.  
    IEnumerable<string> binaryCollection = binaryArray.Select(element => Convert.ToString(element, 2).PadLeft(8, '0'));
  199.  
    string binaryString = string.Join("", binaryCollection);
  200.  
    Console.WriteLine($"转化为【{totalBitCount}】位二进制,为【{string.Join("\x20", binaryCollection)}】");
  201.  
    string signString = (binaryString[0] == '1' ? "-" : " ");
  202.  
    Console.WriteLine($"符号位占用【{signBitCount}】位,为【{signString}】");
  203.  
    string exponent = binaryString.Substring(1, exponentBitCount);
  204.  
    int shiftCount = Convert.ToInt32(exponent, 2) - (1 << (exponentBitCount - 1)) 1;
  205.  
    Console.WriteLine($"指数位为【{exponentBitCount}】位【{exponent}】,对应数字【{Convert.ToInt32(exponent, 2)}】,共移动【{shiftCount}】位");
  206.  
    string mantissa = binaryString.Substring(signBitCount exponentBitCount);
  207.  
    string dotString = $"1.{mantissa}";
  208.  
    Console.WriteLine($"尾数位为【{mantissaBitCount}】位【{mantissa}】,尾数位前面添加一个1并插入移位小数点,字符串为【{dotString}乘以2的{shiftCount}次方】");
  209.  
    dotString = dotString.Replace(".", "").Insert(shiftCount 1, ".");
  210.  
    Console.WriteLine($"即【{dotString}】");
  211.  
    string integerPart = dotString.Substring(0, shiftCount 1);//整数部分
  212.  
    string fractionalPart = dotString.Substring(shiftCount 2);//小数部分
  213.  
     
  214.  
    //整数部分:从低位到高位 依次是2的0次方,2个1次方,2的2次方,然后累加
  215.  
    long numberInteger = 0L;
  216.  
    for (int i = 0; i < integerPart.Length; i )
  217.  
    {
  218.  
    if (integerPart[i] == '1')
  219.  
    {
  220.  
    numberInteger = (1L << (integerPart.Length - 1 - i));
  221.  
    }
  222.  
    }
  223.  
    //小数部分:从小数点开始分别是2的-1次幂、-2次幂、-3次幂……
  224.  
    decimal numberFractional = 0M;
  225.  
    for (int i = 0; i < fractionalPart.Length; i )
  226.  
    {
  227.  
    if (fractionalPart[i] == '1')
  228.  
    {
  229.  
    numberFractional = (decimal)Math.Pow(2, -1 - i);
  230.  
    }
  231.  
    }
  232.  
    Console.WriteLine($"整数部分【{integerPart}】,对应整数为【{numberInteger}】.或者使用Convert,整数也为【{Convert.ToInt64(integerPart, 2)}】");
  233.  
    Console.WriteLine($"小数部分【{fractionalPart}】,对应小数【{numberFractional}】");
  234.  
    string destNumber = $"{signString}{numberInteger numberFractional}";
  235.  
    if (typeof(T) == typeof(float))
  236.  
    {
  237.  
    Console.WriteLine($"【{totalBitCount}】位二进制对应的浮点数为【{destNumber}】,使用BitConverter转换为浮点数的结果为【{BitConverter.ToSingle(binaryArraySource, 0)}】");
  238.  
    return (T)(object)float.Parse(destNumber);
  239.  
    }
  240.  
    else
  241.  
    {
  242.  
    Console.WriteLine($"【{totalBitCount}】位二进制对应的浮点数为【{destNumber}】,使用BitConverter转换为浮点数的结果为【{BitConverter.ToDouble(binaryArraySource, 0)}】");
  243.  
    return (T)(object)double.Parse(destNumber);
  244.  
    }
  245.  
    }
  246.  
    }
  247.  
    }
学新通

程序运行如图:

学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgheihi
系列文章
更多 icon
同类精品
更多 icon
继续加载