截取两位小数,不进行四舍五入。
截取两位小数,不进行四舍五入。
假设我有一个值为3.4679,想要保留两位小数为3.46,如何截取而不进行四舍五入?我尝试了以下方法,但三种方法都给出了3.47:
void Main() { Console.Write(Math.Round(3.4679, 2, MidpointRounding.ToEven)); Console.Write(Math.Round(3.4679, 2, MidpointRounding.AwayFromZero)); Console.Write(Math.Round(3.4679, 2)); }
以下方法返回了3.46,但感觉有点不规范:
void Main() { Console.Write(Math.Round(3.46799999999 - 0.005, 2)); }
问题出现的原因是,C#中没有一个完整的函数来截断一个小数,而不是四舍五入。为了解决这个问题,可以通过将其转换为Decimal扩展方法来实现。以下是实现这个功能的C#和VB.NET代码示例:
C#代码:
public decimal TruncateDecimal(decimal value, int precision) { decimal step = (decimal)Math.Pow(10, precision); decimal tmp = Math.Truncate(step * value); return tmp / step; }
VB.NET代码:
Function TruncateDecimal(value As Decimal, precision As Integer) As Decimal Dim stepper As Decimal = Math.Pow(10, precision) Dim tmp As Decimal = Math.Truncate(stepper * value) Return tmp / stepper End Function
使用示例:
decimal result = TruncateDecimal(0.275, 2);
或
Dim result As Decimal = TruncateDecimal(0.275, 2)
然而,这种方法在处理较大的数字时会导致溢出。另外,使用Int32作为中间变量会导致溢出。如果确实需要将其转换为整数,应该使用Int64。但为什么要额外增加这个开销呢?因为Truncate方法已经返回了Decimal类型的整数部分,所以可以简化为以下代码:
decimal step = (decimal)Math.Pow(10, precision); return Math.Truncate(step * value) / step;
这样就省去了类型转换的步骤,并提高了代码的可读性和理解性。
问题的出现原因:
在处理十进制数时,有时需要截取小数点后两位,但不进行四舍五入。然而,使用Math.Round()方法进行截取时,默认会进行四舍五入,因此需要寻找一种通用快速的方法来实现截取两位小数而不进行四舍五入。
解决方法:
下面提供了一种通用且快速的解决方法,适用于System.Decimal类型的数值。该方法是通过Math.Round()方法进行截取,然后通过一系列的判断和计算来判断是否需要进行调整,从而实现截取两位小数而不进行四舍五入。
解决方法的代码如下(C#语言):
decimal Truncate(decimal d, byte decimals) { decimal r = Math.Round(d, decimals); if (d > 0 && r > d) { return r - new decimal(1, 0, 0, false, decimals); } else if (d < 0 && r < d) { return r + new decimal(1, 0, 0, false, decimals); } return r; }
这段代码经过了其他答案中提到的所有测试,并且完美地通过了这些测试。不过令人惊讶的是,它并没有得到更多的赞同。需要注意的是,十进制数的小数位数只能在0到28之间(对大多数人来说应该足够了)。
其他用户对这个解答进行了一些评价,认为这是最好的答案,也表示支持和赞同。
在使用这个方法时,可以按照以下方式调用:
var truncated = Truncate(decimalNumber, (byte)decimalPlaces);
其中,decimalNumber是decimal类型的数值,decimalPlaces是int类型的数值。