C#通用的二进制转化为float和double方法
二进制转化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 第十位开始】尾数23位前面加一个1,凑够24位,这个24位尾数的前【shiftCount 1】个数就是整数部分,剩下的就是小数部分 |
double(LReal、Double) | 64位 |
第一位为1代表负数,第一位为0代表正数或者0 第十三位开始】尾数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);
-
}
-
}
-
}
-
}
程序运行如图:
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgheihi
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
怎样阻止微信小程序自动打开
PHP中文网 06-13