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

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

二进制转化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(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(binary32ArraySource);
                Console.WriteLine(fNumber);
                dNumber = BinaryBitToFractional(binary64ArraySource);
                Console.WriteLine(dNumber);
            }
            catch (Exception ex) 
            {
                Console.WriteLine(ex.Message);
            }
            Console.ReadLine(); 
        }
        /// 
        /// 32位二进制转化为对应的浮点数float【Real】
        /// 
        /// 
        /// 
        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 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);
        }
        /// 
        /// 64位二进制转化为对应的双精度浮点数double【Double】
        /// 
        /// 
        /// 
        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 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);
        }
        /// 
        /// 通用的二进制32位或64位 转浮点小数
        /// 
        /// 仅支持float和double
        /// 
        /// 
        private static T BinaryBitToFractional(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 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);
            }
        }
    }
}

程序运行如图:

Python判断:if语句和条件表达式完全指南

作为一名Python开发者,我深知条件判断在编程中的重要性。今天,让我们一起深入探讨Python中的判断语句,掌握这个编程中的核心概念。

条件判断的基石:if语句

Python的if语句是实现条件判断的基础工具。它不仅语法简洁,还具有强大的表达能力。主要特点包括:

环境准备与基础配置

Python内置了完整的条件判断功能,无需额外安装任何库。环境要求:

1. 安装Python 3.x版本(推荐3.8+)

2. 配置好Python环境变量

3. 准备一个代码编辑器(推荐PyCharm或VS Code)

代码测试建议使用交互式环境(Python IDLE)或Jupyter Notebook,便于快速验证结果。

条件判断入门教程

让我们通过实例来学习条件判断的基本用法:

# 基本if语句
age = 18
if age >= 18:
    print("已成年")
else:
    print("未成年")

# 多重条件判断
score = 85
if score >= 90:
    grade = 'A'
elif score >= 80:
    grade = 'B'
elif score >= 70:
    grade = 'C'
else:
    grade = 'D'

# 逻辑运算符的使用
is_student = True
has_card = True
if is_student and has_card:
    print("可以享受学生优惠")

需要注意的关键点:

1. 冒号和缩进的正确使用

2. 条件表达式的书写规范

3. 多重条件的优先级

4. 布尔值的判断技巧

进阶应用与最佳实践

在实际开发中,我们常常需要处理更复杂的判断场景:

# 条件表达式(三元运算符)
age = 20
status = "成年" if age >= 18 else "未成年"

# 链式比较
score = 75
if 60 <= score <= 100:
    print("成绩有效")

# 使用in进行成员判断
fruits = ['apple''banana''orange']
if 'apple' in fruits:
    print("找到了苹果")

# 空值判断的最佳实践
data = []
if data:  # 比 if len(data) > 0 更简洁
    print("列表不为空")

高级技巧:

未来可期

Python的条件判断功能在不断进化,新版本引入了更多便捷特性。掌握好判断语句,可以帮助我们写出更优雅的代码。让我们持续学习,在编程道路上走得更远。

本站内容来自用户投稿,如果侵犯了您的权利,请与我们联系删除。联系邮箱:835971066@qq.com

本文链接:http://news.xiuzhanwang.com/post/2916.html

发表评论

评论列表

还没有评论,快来说点什么吧~

友情链接: