C# Decimal类型二进制转换

news/2025/2/26 12:16:18/文章来源:https://www.cnblogs.com/zhangyukof/p/18738191

转载文章请标明原文地址:https://segmentfault.com/a/1190000046149521

一、表示规则

1.内存排布

C#中的decimal类型占16字节,内存排布如下:
flags(32位 符号1位+缩放因子8位)|high(32位)|low + mid(64位)
S0000000 CCCCCCCC 00000000 00000000 | HHHHHHHH HHHHHHHH HHHHHHHH HHHHHHHH | LLLLLLLL LLLLLLLL LLLLLLLL LLLLLLLL | MMMMMMMM MMMMMMMM MMMMMMMM MMMMMMMM

2.关键源码

Decimal源码

private const int SignMask = unchecked((int)0x80000000);
// NOTE: Do not change the order and types of these fields. The layout has to
// match Win32 DECIMAL type.
private readonly int _flags;
private readonly uint _hi32;
private readonly ulong _lo64;public Decimal(int lo, int mid, int hi, bool isNegative, byte scale)
{ArgumentOutOfRangeException.ThrowIfGreaterThan(scale, 28);_lo64 = (uint)lo + ((ulong)(uint)mid << 32);_hi32 = (uint)hi;_flags = ((int)scale) << 16;if (isNegative)_flags |= SignMask;
}

二、代码实现

1.decimal转二进制

private static byte[] WriteDecimal(decimal value) {/*// 推荐用decimal.GetBits(value) 方法获取decimal的四个部分 这里为了性能更好 就用了指针直接读内存int[] parts = decimal.GetBits(value);int low = parts[0];int mid = parts[1];int high = parts[2];int flags = parts[3];*/uint flags;uint high;uint low;uint mid;unsafe {// Decimal源码:int _flags; uint _hi32; ulong _lo64; _lo64 = (uint)lo + ((ulong)(uint)mid << 32);uint* ptr = (uint*)&value;flags = ptr[0]; // int _flagshigh = ptr[1];  // uint _hi32low = ptr[2];   // ulong _lo64 低32位mid = ptr[3];   // ulong _lo64 高32位}bool isNegative = (flags & 0x80000000) != 0; // 取flags的最高位(0为非负值 1为负值)byte scale = (byte)((flags >> 16) & 0x1F);   // 取flags第17位开始的低8位(最大数值28)byte[] bytes = new byte[14];bytes[0] = isNegative ? (byte)1 : (byte)0;bytes[1] = scale;bytes[2] = (byte)low;bytes[3] = (byte)(low >> 8);bytes[4] = (byte)(low >> 16);bytes[5] = (byte)(low >> 24);bytes[6] = (byte)mid;bytes[7] = (byte)(mid >> 8);bytes[8] = (byte)(mid >> 16);bytes[9] = (byte)(mid >> 24);bytes[10] = (byte)high;bytes[11] = (byte)(high >> 8);bytes[12] = (byte)(high >> 16);bytes[13] = (byte)(high >> 24);return bytes;
}

2.二进制转decimal

private static decimal ReadDecimal(byte[] bytes) {bool isNegative = bytes[0] != 0;byte scale = bytes[1];int low = bytes[2] | bytes[3] << 8 | bytes[4] << 16 | bytes[5] << 24;int mid = bytes[6] | bytes[7] << 8 | bytes[8] << 16 | bytes[9] << 24;int high = bytes[10] | bytes[11] << 8 | bytes[12] << 16 | bytes[13] << 24;return new decimal(low, mid, high, isNegative, scale);
}

三、总结

1.精度丢失问题

decimal不会产生精度丢失问题。因为decimal是基于十进制的科学计数法表示的、与float和double的基于二进制科学计数法表示的规则不同,所以不会产生精度丢失问题,在对小数计算敏感的场景里,建议用decimal代替float和double。

2.内存排布问题

decimal内存排布由于实现方式的原因,并不是flags、high、mid、low这种排布方法,用指针获取值时需要注意。

3.序列化和网络传输问题

由于不同编程语言中,类似decimal类型的定义标准和实现原理差异巨大,所以decimal的序列化和网络传输建议转为字符串,字符串可以在不同语言之间转为decimal类型。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTTPS 与 HTTP 的区别在哪?

HTTP与HTTPS作为互联网数据传输的核心协议,其通信机制与安全特性深刻影响着现代网络应用的可靠性与用户体验。它们有什么不同?HTTPS到底安全在哪里?HTTP与HTTPS作为互联网数据传输的核心协议,其通信机制与安全特性深刻影响着现代网络应用的可靠性与用户体验。本文将解析两者…

Featurewiz-Polars:一种强大且可扩展的特征选择解决方案,适用于XGBoost

前言:“Featurewiz-Polars”是一个用于特征工程的 Python 库,结合了特征选择和特征生成的功能。它基于“Polars”,这是一个高性能的 DataFrame 库,用于处理大型数据集,具有类似 Pandas 的 API 但更高效,尤其在处理大数据时。Featurewiz-Polars 专注于通过自动化方式,快速…

USACO2025FEB Gold T1 T2 题解

T3 等会补USACO2025FEB Gold 题解 赛时先看 T1,感觉很可做,推了一下发现能把问题转成在基环树上 dp。但我一下子没太想明白怎么解决“在基环树上找环”这个世纪难题,大概在一个小时 20 分钟的时候写完代码(值得一提的是这次罕见地一次就过了编译),交上去发现 WA 了大约一…

Windows10/Windows11系统快速安装杜比音效经典版教程指南

点击上方蓝字关注我 前言 在当今的数字娱乐时代,音频质量已经成为我们追求的重要部分。杜比音效,凭借其卓越的音质和沉浸式的听觉体验,成为了众多音频爱好者的首选,安装杜比音效经典版,提升电脑音频体验。无论是对于追求极致音质的音乐发烧友,还是渴望在观影和游戏时获得…

No.12 HTML5--新增标签

一、HTML5和HTMLHTML5是 HTML 最新的修订版本,2014年10月由万维网联盟(W3C)完成标准制定。 在 HTML5出现之前,我们一般采用 DIV+CSS 布局我们的页面。但是这样的布局方式不仅使我们的文档结构不够清浙,而且不利于搜索引擎爬虫对我们页面的爬取。为了解决上述缺点,HTML5新增…

ICLR 2025 | 无需训练的Token级 DiT加速方法

前言 本文分享 ICLR 2025 论文 ToCa: Accelerating Diffusion Transformers with Token-wise Feature Caching,提出的 ToCa 模型通过 token 粒度的缓存方法,实现了图像和视频生成模型上无需训练的两倍以上的加速。 欢迎关注公众号CV技术指南,专注于计算机视觉的技术总结、最…

Ⅱ.数据的机器级表示

章节导论: 2.1 位和数据类型 2.1.1 信息最小单位-位(0和1)(如高电压(0.9-1.1v)和低电压(0.0-0.2v)) 2.1.2 数据类型 2.2 整数 2.2.1 无符号整数 位置计数法:通过各个位置的数字不同的权重来表示一个数字 如286=2*102+8*101+6 ,在这个十进制系统中基数为10,同理,二进…

生产CPU打满问题排查

运行好好的系统,突然Prometheus告警,CUP使用率95%告警。赶紧排查一下。 一、先用top -H 命令查看占用CUP高的是哪个进程,看到PID:32518 的进程占用cup过高 二、用top -Hp 32518看看占用资源最多的线程 三、用jstack 32518 > 32518.jstack.log 命令把线程堆栈打印出来四、使…

3 2000年英语一阅读理解Text3

3 2000年英语一阅读理解Text3When a new movement in art attains a certain fashion, it is advisable to find out what its advocates are aiming at, for, however farfetched and unreasonable their principles may seem today, it is possible that in years to come th…

网盘批量分享,转存,重命名,资源监控,数据同步工具

在当今数字化时代,网盘已成为我们存储和分享文件的重要工具。然而,面对多个网盘和账号,如何高效管理这些资源成为了许多用户的难题。为此,我们推出了一款多功能网盘管理工具,旨在帮助用户轻松实现批量操作、资源监控和数据同步,提升文件管理效率。核心功能批量分享与转存…

若依开后端开发常见问题

前端填写完数据后点击提交,出现以上错误,很明显是时间格式出了问题,来看一下后端控制台:可以看出是没有统一时间格式导致的,此类情况请检查后端代码,可以在LocalDateTime类型的时间属性上增加@JsonFormat注解,效果如下:修改完成后问题解决

Beats详解

一、Beats平台介绍 1.1 Beats介绍Beats是开源数据发送者,可以将其作为代理安装在您的服务器上,以将不同类型的运营数据发送到Elasticsearch。Beats可以直接发送数据到Elasticsearch或通过Logstash发送到Elasticsearch,可以使用它来分析和转换数据。 Packetbeat,Fileb…