この記事は公開から3年以上経過しています。
.NETで小数を扱う際、例えば1.235
を小数第二位までを残して残りを切り捨てた1.23
のように、小数第n位までの値を取得する方法。
サンプルソースコード
C#
static class Extensions
{
// 小数を指定した位まで残して切り捨て
public static T Truncate<T>(this T source, int numOfDecimalPlaces) where T: IConvertible
{
decimal d = Convert.ToDecimal(source);
decimal o = (decimal)Math.Pow(10, numOfDecimalPlaces);
return (T)Convert.ChangeType(Math.Truncate(d * o) / o, typeof(T));
}
}
VB.NET
Imports System.Runtime.CompilerServices
Module Extensions
' 小数を指定した位まで残して切り捨て
<Extension>
Public Function Truncate(Of T As {IConvertible})(source As T, numOfDecimalPlaces As Integer) As T
Dim d As Decimal = Convert.ToDecimal(source)
Dim o As Decimal = CDec(Math.Pow(10, numOfDecimalPlaces))
Return CType(Convert.ChangeType(Math.Truncate(d * o) / o, GetType(T)), T)
End Function
End Module
使い方
Float/Double/Decimalなど任意の数値に、本拡張メソッド.Truncate(残す小数の位)
を付加します。
実行結果
幾つかのパターンで実行した結果は以下のとおりです。
検証コード(C#):
var dbl_b = 1234.5678d;
var dbl_a = dbl_b.Truncate(2);
Console.WriteLine($"Dobule値'{dbl_b}'の小数第二位まで = {dbl_a}");
var dbl_b2 = 0.0001d;
var dbl_a2 = dbl_b2.Truncate(3);
Console.WriteLine($"Double値'{dbl_b2}'の小数第三位まで = {dbl_a2}");
var dec_b = 0.1357896m;
var dec_a = dec_b.Truncate(6);
Console.WriteLine($"Decimal値'{dec_b}'の小数第六位まで = {dec_a}");
var int_b = 1;
var int_a = int_b.Truncate(2);
Console.WriteLine($"Int値'{int_b}'の小数第二位まで = {int_a}");
var flt_b = 0.175f;
var flt_a = flt_b.Truncate(1);
Console.WriteLine($"Float値'{flt_b}'の小数第一位まで = {flt_a}");
出力結果:
Dobule値'1234.5678'の小数第二位まで = 1234.56
Double値'0.0001'の小数第三位まで = 0
Decimal値'0.1357896'の小数第六位まで = 0.135789
Int値'1'の小数第二位まで = 1
Float値'0.175'の小数第一位まで = 0.1
ちなみに気になる処理コストですが、切り捨て処理を単純ループで100万回実行した結果が
- double型 … 約373ms
- decimal型 … 約293ms
でしたので、画面や帳票出力用として変換を行う場合などについては十分なパフォーマンスではないかと思います。
※Laptop PC(Core i7 10710U 1.1GHz/電源接続あり/最高パフォーマンス設定/Framework4.7.2)で、デバッガを用いて検証。
以上です。