将数字截断到指定的小数位

我需要将一个数字截断到2位小数,这基本上意味着要删除多余的数字。

例如:

2.919 -> 2.91 2.91111 -> 2.91 

为什么? 这是SQL Server在存储多个特定精度时正在执行的操作。 例如,如果列是十进制(8,2),并且您尝试插入/更新9.1234的数字,则将切断3和4。

我需要在c#代码中做同样的事情。

我能想到的唯一可能的方法是:

  1. 使用stringformatter将其“打印”出两个小数位,然后将其转换为小数,例如:

      decimal tooManyDigits = 2.1345 decimal ShorterDigits = Convert.ToDecimal(tooManyDigits.ToString("0.##")); // ShorterDigits is now 2.13 

    我对此不满意,因为它涉及到一个字符串,然后是另一个字符串到十进制转换,这似乎有点疯狂。

  2. 使用Math.Truncate(只接受一个整数),所以我可以将它乘以100,截断它,然后除以100.例如:

     decimal tooLongDecimal = 2.1235; tooLongDecimal = Math.Truncate(tooLongDecimal * 100) / 100; 

    我也对此不满意,因为如果tooLongDecimal为0,我将得到除以0的错误。

当然有更好的+更简单的方法! 有什么建议?

你自己回答了这个问题; 你似乎只是误解了零除的意思。 执行此操作的正确方法是乘以,截断,然后分配,如下所示:

 decimal TruncateTo100ths(decimal d) { return Math.Truncate(d* 100) / 100; } TruncateTo100ths(0m); // 0 TruncateTo100ths(2.919m); // 2.91 TruncateTo100ths(2.91111m); // 2.91 TruncateTo100ths(2.1345m); // 2.13 

这里没有除零,只有100除,这是绝对安全的。

先前提供的数学解决方案易于溢出大量数字和/或大量小数位。 请考虑以下扩展名:

 [System.Runtime.CompilerServices.Extension()] public static decimal TruncateDecimal(decimal d, int decimals) { if (decimals < 0) throw new ArgumentOutOfRangeException("decimals", "Value must be in range 0-28."); else if (decimals > 28) throw new ArgumentOutOfRangeException("decimals", "Value must be in range 0-28."); else if (decimals = 0) return Math.Truncate(d); else { decimal integerPart = Math.Truncate(d); decimal scalingFactor = d - integerPart; decimal multiplier = Math.Pow(10, decimals); scalingFactor = Math.Truncate(scalingFactor * multiplier) / multiplier; return integerPart + scalingFactor; } } 

用法:

 decimal value = 18446744073709551615.262626263m; value = value.TruncateDecimal(6); 

我同意pswg我有类似的要求,这是我的经验和截断的更广义的function。

http://snathani.blogspot.com/2014/05/truncating-number-to-specificnumber-of.html

 public static decimal Truncate(decimal value, int decimals) { decimal factor = (decimal)Math.Pow(10, decimals); decimal result = Math.Truncate(factor * value) / factor; return result; } 

使用decimal.ToString('0.##') 也会强制舍入:

 1.119M.ToString("0.##") // -> 1.12 

(是的,可能应该是一个评论,但这样很难格式化。)