Как отформатировать десятичное число без конечных нулей
Я только что узнал, что десятичный знак каким-то образом помнит, сколько требующих нулевого значения было необходимо для хранения числа. Другими словами: он запоминает размер фракции.
Например:
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
Удаление нулей в конце новой строки для меня не является реальным вариантом, потому что тогда мне нужно выяснить, содержит ли строка дробь, и если да, то также нужно удалить необязательный параметр. или ',' в зависимости от культуры и т.д.
Ответы
Ответ 1
Есть несколько способов сделать это, но так как вы все равно конвертируете в объект String, я думаю, вы можете попробовать что-то вроде этого:
myDecimalVariable.ToString("G29");
или, используя ваш код выше, предполагая, что 123.00M
является вашим десятичным числом:
123.00M.ToString("G29");
Вот объяснение того, как работает этот краткий пример:
Формат G с числом означает форматирование многих значимых цифры. Потому что 29 является наиболее значимой цифрой, что десятичная дробь может есть, это будет эффективно обрезать конечные нули без округления.
Ответ 2
Метод ниже (🦍) имеет дело со следующими крайними случаями:
- Ввод: 123.00M, ожидание "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 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 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");
}
Ответ 3
просто примените спецификатор формата ноль и удалит завершающие нули:
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');