C#十进制,如何添加尾随零 [英] C# decimal, how to add trailing zeros

查看:84
本文介绍了C#十进制,如何添加尾随零的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须将尾随零添加到十进制值.不仅用于显示(因此不能选择Format),而且还用于显示实际的基础数据,因为十进制精度在我们的应用程序中很重要.

I have to add trailing zeros to a decimal value. Not only for displaying (so Format is not an option), but in the actual underlying data, because the decimal precision is important in our application.

我尝试过:

decimal value = 1M
decimal withPrecision = value + 0.000M;

在许多情况下效果很好...奇怪的是,在所有情况下效果都不佳.我调试了withPrecision中的值仍然为1M的情况,方法是在运行时看不到该值的任何差异,并且在即时窗口中看不到相同的硬编码值.我还使用了decimal.GetBits来发现差异-没有差异.

Which works well in many cases ... strangely not in all. I debugged into a case where the value in withPrecision was still 1M, by not seeing any difference in the value at runtime and the same hardcoded value in the immediate window. I also used decimal.GetBits to find differences - there are none.

我尝试过(按照此处的建议调整小数精度.net ):

I tried (as proposed here Adjusting decimal precision, .net):

decimal value = 1M
decimal withPrecision = value * 1.000M;

效果很好-除大小写为零外.那么结果是0M,没有任何尾随零.我也不信任该解决方案,在其他情况下也可能不起作用.

which works well - except for the case value is zero. Then the result is 0M without any trailing zeros. I also do not trust the solution, it may also not work in other cases.

目前我在:

decimal value = 1M
decimal withPrecision = (value * 1.000M) + 0.000M;

我在当前发现的所有情况下都能工作……但看起来也不是很值得信赖.我还可以实现零的特殊情况.

Which works in all cases I currently found ... but doesn't look very trustworthy neither. I could also implement an exceptional case for zeros.

我认为FormatParse可以工作.我不太喜欢它看起来不太快,我也不明白为什么我必须将十进制数放入字符串中才能对其进行操作.

I think Format and Parse would work. I don't like it much. It doesn't look very fast and I don't understand why I have to put the decimal into a string just to manipulate it.

我开始相信,对于这样一个简单的任务,没有干净的解决方案.

I start to believe that there is no clean solution for such a simple task.

推荐答案

A decimal占用128位(16字节),其中1位用于符号,96位(12字节)用于实际符号.值和5位用于存储小数点的位置.

A decimal occupies 128 bits (16 bytes), of which 1 bit is used for the sign, 96 bits (12 bytes) are used for the actual value and 5 bits are used to store the position of the decimal point.

当C#编译器看到1M时,它将解析为{sign: 0, value: 1, point: 0},而将1.0M解析为{sign: 0, value: 10, point: 1}.但是,两者都表示相同的值(1M == 1.0M返回true),并且另一个解析器可以轻松地将1M1.0M都映射到{sign: 0, value: 1, point: 0}.

When the C# compiler sees 1M, it parses it as {sign: 0, value: 1, point: 0}, while 1.0M is parsed as {sign: 0, value: 10, point: 1}. However, both represent the same value (1M == 1.0M returns true), and another parser could easily have mapped both 1M and 1.0M to {sign: 0, value: 1, point: 0}.

1M0.1M一起添加会发生什么? 1M{sign: 0, value: 1, point: 0}0.1M{sign: 0, value: 1, point: 1},因此我们有两个精度不同的数字.但是,这没问题:我们可以通过在1M中的点上添加1并将其值乘以10:{sign: 0, value: 10, point: 1}来移动该点.现在两个数字都具有相同的点位置,我们可以通过简单地将它们的值相加来将它们加在一起,从而得到{sign: 0, value: 11, point: 1},它对应于1.1M.

What happens when you add 1M and 0.1M together? 1M is {sign: 0, value: 1, point: 0} and 0.1M is {sign: 0, value: 1, point: 1}, so we have two numbers with different precision. That's no problem however: we can move the point in 1M by adding 1 to its point and by multiplying its value by 10: {sign: 0, value: 10, point: 1}. Now that both numbers have the same point position, we can add them together by simply adding up their values, which results in {sign: 0, value: 11, point: 1}, which corresponds to 1.1M.

因此decimal的内部表示形式不会影响其操作的精度-只要有必要,小数点位置都会移动(并调整值).*

So the internal representation of a decimal does not affect the precision of its operations - the decimal point position is moved (and the value adjusted) whenever this becomes necessary.*

但是,如果由于某种原因您的小数位绝对必须具有一定的位置(从您到目前为止发布的内容来看,我没有令人信服的理由-格式纯粹是显示问题),那么最简单的方法是使用decimal(int, int, int, bool, byte)构造函数(或替换为decimal(int[])).这使您可以传入值(作为3个整数),符号(作为布尔值)和点位置(作为字节).如果传递的点位置高于0,则必须自己乘以该值:1.000M必须构造为new decimal(1000, 0, 0, false, 3),而不是new decimal(1, 0, 0, false, 3)(因为这样会得到0.001M).

However, if for some reason your decimals absolutely must have a certain point position (and from what you've posted so far, I see no compelling reason - formatting is purely a display issue), then the easiest approach is to use the decimal(int, int, int, bool, byte) constructor (or alternately decimal(int[])). This allows you to pass in the value (as 3 integers), the sign (as a boolean) and the point position (as a byte). You will have to multiply the value yourself if you pass a point position higher than 0: 1.000M must be constructed as new decimal(1000, 0, 0, false, 3), not as new decimal(1, 0, 0, false, 3) (because that would give you 0.001M).

*点的位置限制为[0-28],因此decimal不能表示点后超过28位的数字.同样,该值必须在点前面和点后面的数字之间分割",因此,非常大的数字将限制可用精度,可能会降低它的大小,以表示点前面的数字.

*the point position is limited to [0-28], so a decimal cannot represent numbers with more than 28 digits behind the dot. Also, the value has to be 'split' between digits in front of the dot and behind the dot, so very large numbers will put restrictions on the available precision, possibly cutting it down in favor of representing the digits in front of the dot.

这篇关于C#十进制,如何添加尾随零的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆