web-dev-qa-db-ja.com

末尾のゼロなしで小数をフォーマットする方法

小数は、数値を格納するために必要な末尾のゼロの量をどういうわけか覚えていることを知りました。言い換えれば、分数のサイズを記憶しています。

例えば:

123M.ToString() ==> resuls in: 123
123.00M.ToString() ==> resuls in: 123.00
123.450M.ToString() ==> resuls in: 123.450

これらの「不要な」後続ゼロを取り除くためのフォーマット文字列または別のトリックを探していますが、有効数字は保持しています。そう:

123M.ToString() ==> resuls in: 123
123.00M.ToString() ==> resuls in: 123
123.450M.ToString() ==> resuls in: 123.45

新しい文字列の末尾にあるゼロを削除することは、私にとって実際のオプションではありません。文字列に分数が含まれているかどうかを確認する必要があり、含まれている場合は、オプションの「。」も削除する必要があるためです。または「、」文化などに応じて。

12
Martin Mulder

それを行うにはいくつかの方法がありますが、とにかくStringオブジェクトに変換しているので、次のようなことを試すことができると思います。

myDecimalVariable.ToString("G29");

または、上記のコードを使用して、_123.00M_が小数であると仮定します。

123.00M.ToString("G29");

その簡潔な例がどのように機能するかについての説明は次のとおりです。

数字の付いたG形式は、その有効桁数をフォーマットすることを意味します。 29は、Decimalが持つことができる最上位桁であるため、これにより、丸めることなく後続のゼロが効果的に切り捨てられます。

12
Mike Hawkins

以下のメソッド(????)は、次のエッジケースを処理します。

  • 入力:123.00M、「123.00」を期待
    • ❌G29:123
    • ✅????:123.00
  • 入力:-0.00000000001M、「-0.00000000001」を期待
    • ❌G29:-1E-11
    • ✅????:-0.00000000001
private static string SlowButStrong(decimal v)
{
  if( v % 1 == 0) return v.ToString(); // If no decimal digits, let's leave it alone
  var withNoZeroes = v.ToString().TrimEnd('0');
  return withNoZeroes.EndsWith('.') ? withNoZeroes + "00" : withNoZeroes;
}

テスト出力

Input 123M, expecting 123
✅ G29: 123
✅ ????: 123
✅ ⛵: 123

Input 123.00M, expecting 123.00
❌ G29: 123
✅ ????: 123.00
❌ ⛵: 123

Input 123.45M, expecting 123.45
✅ G29: 123.45
✅ ????: 123.45
✅ ⛵: 123.45

Input 123.450M, expecting 123.45
✅ G29: 123.45
✅ ????: 123.45
✅ ⛵: 123.45

Input 5.00000001M, expecting 5.00000001
✅ G29: 5.00000001
✅ ????: 5.00000001
✅ ⛵: 5.00000001

Input -0.00000000001M, expecting -0.00000000001
❌ G29: -1E-11
✅ ????: -0.00000000001
✅ ⛵: -0.00000000001

Input 10000000000000000000000M, expecting 10000000000000000000000
✅ G29: 10000000000000000000000
✅ ????: 10000000000000000000000
✅ ⛵: 10000000000000000000000

任意のテストケース

public static void Main(string[] args)
{
    Test("123M", 123M, "123");
    Test("123.00M", 123.00M, "123.00");
    Test("123.45M", 123.45M, "123.45");
    Test("123.450M", 123.450M, "123.45");
    Test("5.00000001M", 5.00000001M, "5.00000001");
    Test("-0.00000000001M", -0.00000000001M, "-0.00000000001");
    Test("10000000000000000000000M", 10000000000000000000000M, "10000000000000000000000");
}

private static void Test(string vs, decimal v, string expected)
{
    Console.OutputEncoding = System.Text.Encoding.UTF8;

    Console.WriteLine($"Input {vs}, expecting {expected}");
    Print("G29", v.ToString("G29"), expected);
    Print("????", SlowButStrong(v), expected);
    Print("⛵", LessSlowButStrong(v), expected);
    Console.WriteLine();
}

private static void Print(string prefix, string formatted, string original)
{
    var mark = formatted == original ? "✅" : "❌"; 
    Console.WriteLine($"{mark} {prefix:10}: {formatted}");
}

private static string SlowButStrong(decimal v)
{
    if( v % 1 == 0) return v.ToString(); // If no decimal digits, let's leave it alone
    var withNoZeroes = v.ToString().TrimEnd('0');
    return withNoZeroes.EndsWith('.') ? withNoZeroes + "00" : withNoZeroes;
}

private static string LessSlowButStrong(decimal v)
{
    return v.ToString((v < 1) ? "" : "G29");
}
0
tymtam

フォーマット指定子ゼロを適用するだけで、末尾のゼロが削除されます。

string test = (1.23M * 100M).ToString("0");
//prints 123.
string test2 = 123.450M.ToString(".00");
//prints 123.45.
string test3 = 123.450M.ToString().Trim('0');
0
terrybozzio