如何有效地确保十进制值至少具有N个小数位 [英] How to efficiently ensure a decimal value has at least N decimal places

查看:56
本文介绍了如何有效地确保十进制值至少具有N个小数位的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在进行算术运算之前,我想有效地确保一个十进制值至少具有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屋!

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