如何有效地确保十进制值至少具有N个小数位 [英] How to efficiently ensure a decimal value has at least N decimal places
问题描述
在进行算术运算之前,我想有效地确保一个十进制值至少具有N(在下面的示例中为= 3)位.
I want to efficiently ensure a decimal value has at least N (=3 in the example below) places, prior to doing arithmetic operations.
我可以先用"0.000 ##### ....#"
进行格式化,然后进行解析,但是效率相对较低,我正在寻找一种避免与之转换的解决方案一个字符串.
Obviouly I could format with "0.000######....#"
then parse, but it's relatively inefficient and I'm looking for a solution that avoids converting to/from a string.
我尝试了以下解决方案:
I've tried the following solution:
decimal d = 1.23M;
d = d + 1.000M - 1;
Console.WriteLine("Result = " + d.ToString()); // 1.230
似乎适用于所有值< = Decimal.MaxValue-1
(在Debug和Release版本中使用Visual Studio 2015编译时).
which seems to work for all values <= Decimal.MaxValue - 1
when compiled using Visual Studio 2015 in both Debug and Release builds.
但是我有点怀疑,编译器可能被允许优化(1.000-1).C#规范中是否有任何东西可以保证始终有效?
But I have a nagging suspicion that compilers may be allowed to optimize out the (1.000 - 1). Is there anything in the C# specification that guarantees this will always work?
还是有更好的解决方案,例如使用 Decimal.GetBits
?
Or is there a better solution, e.g. using Decimal.GetBits
?
更新
按照Jon Skeet的回答,我以前曾尝试添加 0.000M
,但这在dotnetfiddle上不起作用.所以我很惊讶地看到 Decimal.Add(d,0.000M)
确实有效.这里是一个dotnetfiddle 比较 d + 000M
和 decimal.Add(d,0.000万)
:结果与dotnetfiddle不同,但使用Visual Studio 2015编译相同的代码时结果相同:
Following up Jon Skeet's answer, I had previously tried adding 0.000M
, but this didn't work on dotnetfiddle. So I was surprised to see that Decimal.Add(d, 0.000M)
does work. Here's a dotnetfiddle comparing d + 000M
and decimal.Add(d,0.000M)
: the results are different with dotnetfiddle, but identical when the same code is compiled using Visual Studio 2015:
decimal d = 1.23M;
decimal r1 = decimal.Add(d, 0.000M);
decimal r2 = d + 0.000M;
Console.WriteLine("Result1 = " + r1.ToString()); // 1.230
Console.WriteLine("Result2 = " + r2.ToString()); // 1.23 on dotnetfiddle
因此,至少某些行为似乎与编译器相关,这并不能令人放心.
So at least some behavior seems to be compiler-dependent, which isn't reassuring.
推荐答案
如果您担心编译器会优化运算符(尽管我怀疑这样做会优化),则可以调用 Add
方法.请注意,您不需要先添加再减去-您只需添加0.000m.例如:
If you're nervous that the compiler will optimize out the operator (although I doubt that it would ever do so) you could just call the Add
method directly. Note that you don't need to add and then subtract - you can just add 0.000m. So for example:
public static decimal EnsureThreeDecimalPlaces(decimal input) =>
decimal.Add(input, 0.000m);
这似乎很好用-如果您担心编译器将使用常量做什么,您可以 将位保留在数组中,仅将其转换一次:
That appears to work fine - if you're nervous about what the compiler will do with the constant, you could keep the bits in an array, converting it just once:
private static readonly decimal ZeroWithThreeDecimals =
new decimal(new[] { 0, 0, 0, 196608 }); // 0.000m
public static decimal EnsureThreeDecimalPlaces(decimal input) =>
decimal.Add(input, ZeroWithThreeDecimals);
我认为这还是有点过头的-特别是如果您有良好的单元测试.(如果您对将要部署的已编译代码进行测试,那么以后编译器将无法进入那里-我真的很惊讶看到JIT在这里介入.)
I think that's a bit over the top though - particularly if you have good unit tests in place. (If you test against the compiled code you'll be deploying, there's no way the compiler can get in there afterwards - and I'd be really surprised to see the JIT intervene here.)
这篇关于如何有效地确保十进制值至少具有N个小数位的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!