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

news2024/11/25 7:43:44

上一篇,我们将32位二进制【或4个字节】转化为float【Real】小数,这次我们使用通用的方法进行二进制转化。

C#中将32位二进制转换为float【Real】十进制类型_斯内科的博客-CSDN博客

二进制转化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 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BinaryToFloatDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.SetWindowSize(160, 50);
            //单精度浮点数对应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进制)
            byte[] binary32ArraySource = new byte[4] { 80, 32, 241, 71 };
            byte[] binary64ArraySource = new byte[8] { 215, 252, 96, 26, 153, 190, 60, 194 };
            try
            {
                float fNumber = Binary32BitToFloat(binary32ArraySource);
                Console.WriteLine(fNumber);

                double dNumber = Binary64BitToDouble(binary64ArraySource);
                Console.WriteLine(dNumber);

                Console.WriteLine($"-------------下面整体测试通用方法【{nameof(BinaryBitToFractional)}】-------------");
                fNumber = BinaryBitToFractional<float>(binary32ArraySource);
                Console.WriteLine(fNumber);
                dNumber = BinaryBitToFractional<double>(binary64ArraySource);
                Console.WriteLine(dNumber);
            }
            catch (Exception ex) 
            {
                Console.WriteLine(ex.Message);
            }
            Console.ReadLine(); 
        }

        /// <summary>
        /// 32位二进制转化为对应的浮点数float【Real】
        /// </summary>
        /// <param name="binaryArraySource"></param>
        /// <returns></returns>
        private static float Binary32BitToFloat(byte[] binaryArraySource) 
        {
            if (binaryArraySource == null || binaryArraySource.Length != 4) 
            {
                throw new ArgumentException($"源数组不能为空并且有且只有4个元素", nameof(binaryArraySource));
            }
            byte[] binaryArray = binaryArraySource.Reverse().ToArray();
            Console.WriteLine($"将数组顺序反转,反转后为【{string.Join(",", binaryArray)}】");
            IEnumerable<string> binaryCollection = binaryArray.Select(element => Convert.ToString(element, 2).PadLeft(8, '0'));
            string binaryString = string.Join("", binaryCollection);
            Console.WriteLine($"转化为32位二进制,为【{string.Join("\x20", binaryCollection)}】");
            string signString = (binaryString[0] == '1' ? "-" : "+");
            Console.WriteLine($"符号位占用1位,为【{signString}】");
            string exponent = binaryString.Substring(1, 8);
            int shiftCount = Convert.ToInt32(exponent, 2) - 127;
            Console.WriteLine($"指数位为8位【{exponent}】,对应数字【{Convert.ToInt32(exponent, 2)}】,共移动【{shiftCount}】位");
            string mantissa = binaryString.Substring(9);
            string dotString = $"1.{mantissa}";
            Console.WriteLine($"尾数位为23位【{mantissa}】,尾数位前面添加一个1并插入移位小数点,字符串为【{dotString}乘以2的{shiftCount}次方】");
            dotString = dotString.Replace(".", "").Insert(shiftCount + 1, ".");
            Console.WriteLine($"即【{dotString}】");
            string integerPart = dotString.Substring(0, shiftCount + 1);//整数部分
            string fractionalPart = dotString.Substring(shiftCount + 2);//小数部分

            //整数部分:从低位到高位 依次是2的0次方,2个1次方,2的2次方,然后累加
            long numberInteger = 0;
            for (int i = 0; i < integerPart.Length; i++)
            {
                if (integerPart[i] == '1')
                {
                    numberInteger += (1L << (integerPart.Length - 1 - i));
                }
            }
            //小数部分:从小数点开始分别是2的-1次幂、-2次幂、-3次幂……
            decimal numberFractional = 0M;
            for (int i = 0; i < fractionalPart.Length; i++)
            {
                if (fractionalPart[i] == '1')
                {
                    numberFractional += (decimal)Math.Pow(2, -1 - i);
                }
            }
            Console.WriteLine($"整数部分【{integerPart}】,对应整数为【{numberInteger}】.或者使用Convert,整数也为【{Convert.ToInt32(integerPart, 2)}】");
            Console.WriteLine($"小数部分【{fractionalPart}】,对应小数【{numberFractional}】");
            string destNumber = $"{signString}{numberInteger + numberFractional}";
            Console.WriteLine($"32位二进制对应的浮点数为【{destNumber}】,使用BitConverter转换为浮点数的结果为【{BitConverter.ToSingle(binaryArraySource, 0)}】");
            return float.Parse(destNumber);
        }

        /// <summary>
        /// 64位二进制转化为对应的双精度浮点数double【Double】
        /// </summary>
        /// <param name="binaryArraySource"></param>
        /// <returns></returns>
        private static double Binary64BitToDouble(byte[] binaryArraySource)
        {
            if (binaryArraySource == null || binaryArraySource.Length != 8)
            {
                throw new ArgumentException($"源数组不能为空并且有且只有8个元素", nameof(binaryArraySource));
            }
            byte[] binaryArray = binaryArraySource.Reverse().ToArray();
            Console.WriteLine($"将数组顺序反转,反转后为【{string.Join(",", binaryArray)}】");
            IEnumerable<string> binaryCollection = binaryArray.Select(element => Convert.ToString(element, 2).PadLeft(8, '0'));
            string binaryString = string.Join("", binaryCollection);
            Console.WriteLine($"转化为64位二进制,为【{string.Join("\x20", binaryCollection)}】");
            string signString = (binaryString[0] == '1' ? "-" : "+");
            Console.WriteLine($"符号位占用1位,为【{signString}】");
            string exponent = binaryString.Substring(1, 11);
            int shiftCount = Convert.ToInt32(exponent, 2) - 1023;
            Console.WriteLine($"指数位为8位【{exponent}】,对应数字【{Convert.ToInt32(exponent, 2)}】,共移动【{shiftCount}】位");
            string mantissa = binaryString.Substring(12);
            string dotString = $"1.{mantissa}";
            Console.WriteLine($"尾数位为52位【{mantissa}】,尾数位前面添加一个1并插入移位小数点,字符串为【{dotString}乘以2的{shiftCount}次方】");
            dotString = dotString.Replace(".", "").Insert(shiftCount + 1, ".");
            Console.WriteLine($"即【{dotString}】");
            string integerPart = dotString.Substring(0, shiftCount + 1);//整数部分
            string fractionalPart = dotString.Substring(shiftCount + 2);//小数部分

            //整数部分:从低位到高位 依次是2的0次方,2个1次方,2的2次方,然后累加
            long numberInteger = 0L;
            for (int i = 0; i < integerPart.Length; i++)
            {
                if (integerPart[i] == '1')
                {
                    numberInteger += (1L << (integerPart.Length - 1 - i));
                }
            }
            //小数部分:从小数点开始分别是2的-1次幂、-2次幂、-3次幂……
            decimal numberFractional = 0M;
            for (int i = 0; i < fractionalPart.Length; i++)
            {
                if (fractionalPart[i] == '1')
                {
                    numberFractional += (decimal)Math.Pow(2, -1 - i);
                }
            }
            Console.WriteLine($"整数部分【{integerPart}】,对应整数为【{numberInteger}】.或者使用Convert,整数也为【{Convert.ToInt64(integerPart, 2)}】");
            Console.WriteLine($"小数部分【{fractionalPart}】,对应小数【{numberFractional}】");
            string destNumber = $"{signString}{numberInteger + numberFractional}";
            Console.WriteLine($"64位二进制对应的浮点数为【{destNumber}】,使用BitConverter转换为浮点数的结果为【{BitConverter.ToDouble(binaryArraySource, 0)}】");
            return double.Parse(destNumber);
        }

        /// <summary>
        /// 通用的二进制32位或64位 转浮点小数
        /// </summary>
        /// <typeparam name="T">仅支持float和double</typeparam>
        /// <param name="binaryArraySource"></param>
        /// <returns></returns>
        private static T BinaryBitToFractional<T>(byte[] binaryArraySource) where T : struct 
        {
            if (typeof(T) != typeof(float) && typeof(T) != typeof(double)) 
            {
                throw new Exception($"类型错误,必须是浮点数类型【float或double】");
            }
            if (binaryArraySource == null) 
            {
                throw new ArgumentException($"源数组不能为空", nameof(binaryArraySource));
            }
            if (typeof(T) == typeof(float) && binaryArraySource.Length != 4)
            {
                throw new ArgumentException($"转化为float时,源数组必须有且只有4个元素", nameof(binaryArraySource));
            }
            if (typeof(T) == typeof(double) && binaryArraySource.Length != 8)
            {
                throw new ArgumentException($"转化为double时,源数组必须有且只有8个元素", nameof(binaryArraySource));
            }

            //单精度float:N共32位,其中S占1位,E占8位,M占23位。因此小数点后最多精确到23/4=6位 
            int signBitCount = 1;//符号位数,代表正数还是负数
            int exponentBitCount = 8;//指数位数
            int mantissaBitCount = 23;//尾数位数
            int totalBitCount = 32;//二进制总位数
            if (typeof(T) == typeof(double))
            {
                //双精度double:N共64位,其中S占1位,E占11位,M占52位。因此小数点后最多精确到52/4=13位 
                exponentBitCount = 11;//指数位数
                mantissaBitCount = 52;//尾数位数
                totalBitCount = 64;//二进制总位数
            }
            byte[] binaryArray = binaryArraySource.Reverse().ToArray();
            Console.WriteLine($"将数组顺序反转,反转后为【{string.Join(",", binaryArray)}】");
            IEnumerable<string> binaryCollection = binaryArray.Select(element => Convert.ToString(element, 2).PadLeft(8, '0'));
            string binaryString = string.Join("", binaryCollection);
            Console.WriteLine($"转化为【{totalBitCount}】位二进制,为【{string.Join("\x20", binaryCollection)}】");
            string signString = (binaryString[0] == '1' ? "-" : "+");
            Console.WriteLine($"符号位占用【{signBitCount}】位,为【{signString}】");
            string exponent = binaryString.Substring(1, exponentBitCount);
            int shiftCount = Convert.ToInt32(exponent, 2) - (1 << (exponentBitCount - 1)) + 1;
            Console.WriteLine($"指数位为【{exponentBitCount}】位【{exponent}】,对应数字【{Convert.ToInt32(exponent, 2)}】,共移动【{shiftCount}】位");
            string mantissa = binaryString.Substring(signBitCount + exponentBitCount);
            string dotString = $"1.{mantissa}";
            Console.WriteLine($"尾数位为【{mantissaBitCount}】位【{mantissa}】,尾数位前面添加一个1并插入移位小数点,字符串为【{dotString}乘以2的{shiftCount}次方】");
            dotString = dotString.Replace(".", "").Insert(shiftCount + 1, ".");
            Console.WriteLine($"即【{dotString}】");
            string integerPart = dotString.Substring(0, shiftCount + 1);//整数部分
            string fractionalPart = dotString.Substring(shiftCount + 2);//小数部分

            //整数部分:从低位到高位 依次是2的0次方,2个1次方,2的2次方,然后累加
            long numberInteger = 0L;
            for (int i = 0; i < integerPart.Length; i++)
            {
                if (integerPart[i] == '1')
                {
                    numberInteger += (1L << (integerPart.Length - 1 - i));
                }
            }
            //小数部分:从小数点开始分别是2的-1次幂、-2次幂、-3次幂……
            decimal numberFractional = 0M;
            for (int i = 0; i < fractionalPart.Length; i++)
            {
                if (fractionalPart[i] == '1')
                {
                    numberFractional += (decimal)Math.Pow(2, -1 - i);
                }
            }
            Console.WriteLine($"整数部分【{integerPart}】,对应整数为【{numberInteger}】.或者使用Convert,整数也为【{Convert.ToInt64(integerPart, 2)}】");
            Console.WriteLine($"小数部分【{fractionalPart}】,对应小数【{numberFractional}】");
            string destNumber = $"{signString}{numberInteger + numberFractional}";
            if (typeof(T) == typeof(float))
            {
                Console.WriteLine($"【{totalBitCount}】位二进制对应的浮点数为【{destNumber}】,使用BitConverter转换为浮点数的结果为【{BitConverter.ToSingle(binaryArraySource, 0)}】");
                return (T)(object)float.Parse(destNumber);
            }
            else 
            {
                Console.WriteLine($"【{totalBitCount}】位二进制对应的浮点数为【{destNumber}】,使用BitConverter转换为浮点数的结果为【{BitConverter.ToDouble(binaryArraySource, 0)}】");
                return (T)(object)double.Parse(destNumber);
            }
        }
    }
}

程序运行如图:

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/555120.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

挖出电商店铺详情数据-API接口分享

在今天的互联网时代&#xff0c;电商平台已经成为了我们生活中不可或缺的一部分。淘宝作为全国最大的电商平台之一&#xff0c;其商品信息也越来越丰富&#xff0c;但是如果你想开发一款能够帮助用户购物的应用程序&#xff0c;就必须获取到淘宝的API接口&#xff0c;才能让你的…

【Webpack】前端工程自动化 - require.context实现模块自动化导入

一、介绍 require.context 是基于 webpack 的一个的 api&#xff0c;主要用来实现模块的自动化导入在前端工程中&#xff0c;如果遇到一个文件需要引入很多模块的情况&#xff0c;可以使用这个apirequire.context 会遍历文件夹中的指定文件&#xff0c;然后自动导入&#xff0…

记一次redis主从切换导致的数据丢失与陷入只读状态故障

背景 最近一组业务redis数据不断增长需要扩容内存&#xff0c;而扩容内存则需要重启云主机&#xff0c;在按计划扩容升级执行主从切换时意外发生了数据丢失与master进入只读状态的故障&#xff0c;这里记录分享一下。 业务redis高可用架构 该组业务redis使用的是一主一从&am…

从“0”到“1”!低代码开发和云计算的碰撞,引领数字化转型浪潮!

随着互联网技术的飞速发展&#xff0c;数字化转型已经成为企业转型升级的必经之路。而在数字化转型的过程中&#xff0c;云计算和低代码开发逐渐成为新技术的代表&#xff0c;为企业提供更高效、更灵活的技术支持&#xff0c;让企业赢得更大的竞争优势。 云计算的发展 云计算是…

三阶段项目

DHCP分配不到冲突地址 需要重启 再分配 用这个命令 reset ip pool name vlan40 all ospf&#xff1a; 建立邻居表&#xff1a;报文&#xff1a;hello报文 状态&#xff1a;down int 2-way 选举DR 同步数据库&#xff1a;报文&#xff1a;DD-LSR-LSU-LSACK 状态&#xff…

C语言-printf打印%*s、%.*s与%-.*s的区别

一、简介 在平时的使用中&#xff0c;会经常使用到printf进行打印&#xff0c;而最长使用的方式是printf("%s",string)进行打印。但是有个问题&#xff0c;如果string结尾不是0。那么printf会继续打印&#xff0c;直到遇到0为止。这样就会有内存溢出的风险。显然&…

(三)ArcGIS空间数据的转换与处理——栅格数据变换

ArcGIS空间数据的转换与处理——栅格数据变换 目录 ArcGIS空间数据的转换与处理——栅格数据变换 1.地理配准2.平移3.扭曲4.旋转5.翻转6.重设比例尺7.镜像 数据变换是指对数据进行诸如放大、缩小、翻转、移动、扭曲等几何位置、形状和方位的改变等操作。对于 栅格数据的相应操…

类和对象 - 练习题(C++)

目录 1、求123...n 题目链接&#xff1a; 题目&#xff1a; 题目描述&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 2 计算日期到天数转换 题目链接&#xff1a; 题目&#xff1a; 题目描述&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 3 日期差值 题目链接&…

人工智能学习07--pytorch18--目标检测:Faster RCNN源码解析(pytorch)

参考博客&#xff1a; https://blog.csdn.net/weixin_46676835/article/details/130175898 VOC2012 1、代码的使用 查看pytorch中的faster-rcnn源码&#xff1a; 在pytorch中导入&#xff1a; import torchvision.models.detection.faster_rcnn即可找到faster rcnn所实现的源…

NIFI分页获取Postgresql数据到Hbase中_实际操作---大数据之Nifi工作笔记0049

首先看一下整体流程,可以看到这里用的PutHbaseJson处理器,把数据导入到 hbase中的 注意这里也可以使用PutSql导入数据,通过phoenix的jdbc驱动,然后把数据利用PutSql处理器导入到 Hbase中,但是我这里的时候报错了,然后一直没解决,所以最后用了PutHbaseJson处理器,把数据存入到…

【LinuxShell】linux防火墙之SNAT策略和DNAT策略

文章目录 前言一、SANT策略1.SNAT策略概述2.SNAT的典型应用环境3.SNAT的工作原理4.SNAT策略的应用SNAT转换前提条件SNAT策略打开方式SNAT实验过程 5.知识扩展 二、DNAT策略1.DNAT策略概述2.DNAT的典型应用环境3.DNAT的工作原理4.DNAT策略的应用DNAT转换前提条件DNAT地址转换方式…

linux管道通信原理

管道&#xff0c;通常指无名管道&#xff0c;是 UNIX 系统IPC&#xff08;InterProcess Communication)最古老的形式。 1、特点: 1.它是半双工的(即数据只能在一个方向上流动) &#xff0c;具有固定的读端和写端 2.它只能用于具有亲缘关系的进程之间的通信(也是子进程或者兄弟进…

python 读写 json,csv,txt,docx,xlsx,xls文件大全

目录 前言一、读写json1.1 读1.2 写1.2.1 list类型写入1.2.2 dict类型写入 二、读写csv2.1 读2.2 写2.2.1 list类型写入2.2.2 dict类型写入 三、读写txt3.1 读3.2 写按行写入&#xff08;手动添加换行符\n&#xff09;按行写入&#xff08;python添加换行符\n&#xff09;3.2.1…

Linux:Firewalld防火墙

Linux&#xff1a;Firewalld防火墙 一、Firewanlld防火墙概述二、Firewalld和Iptables的关系三、Firewalld网络区域3.1 Firewalld 区域的概念&#xff1a;3.2 firewalld防火墙预定义了9个区域3.3 firewalld数据处理流程 四、Firewalld防火墙的配置方法五、Firewalld-config图形…

RHCSA 8考题超级详细解析(2022最新版)本人已过

文章目录 1.配置IP地址2、配置软件仓库3、调试SELinux4、创建用户账户5. 配置cron计划任务6、创建共享目录7、配置NTP时间客户端8. auto自动挂载9、配置文件权限10、配置用户账户11、查找文件12、查找字符串13、 创建归档14、配置sudo提权15、设置密码默认策略16、配置umask值1…

海格里斯HEGERLS库架合一|仓储托盘四向穿梭车在冷库冷链行业中的应用

当前的物流行业正在从劳动密集型向技术密集型转变&#xff0c;物流系统越来越明显的向呈现出自动化、数字化、柔性化、智能化的发展趋势。以堆垛机为代表的自动化仓储系统&#xff0c;取货对场地要求比较高&#xff0c;多建在12M以上的新仓库。而对于不规则的、层高较低的老仓库…

【python资料】热图和Matplotlib.imshow()函数

一、说明 Matplotlib是一个强大的Python数据可视化库&#xff0c;可以绘制各种类型的图形&#xff0c;其中包括热图。热图通常用于表现数据的分布和趋势。本文用一个简单的例子&#xff0c;告诉大家用Matplotlib绘制热图的基本操作语句。 二、热图的概念 2.1 基本概念 热图&am…

7EBG-10-C-B-107EBG-20-B-B-10比例先导溢流阀放大板

7EBG-10-B-B-10、7EBG-20-C-B-10、7EBG-30-H-B-10、7EBG-10-C-B-10、7EBG-20-B-B-10、7EBG-30-C-B-10特性&#xff1a; ● 该阀是由高性能型比例先导式溢流阀和低噪音型溢流阀组合而成&#xff0c;进行压力与输入电流成比例的压力控制&#xff0c;能够达到无段式控制特性。 ●…

c++(内存管理)

本节目标&#xff1a; 1、c/c内存分布 2、c语言中动态内存管理方式 3、c中动态内存管理 4、operator new 与 operator delete函数 5、new和delete的实现原理 6、定位new表达式&#xff08;placement - new&#xff09; 7、常见面试题 目录 1.c/c内存分布 2、c语言中动…