Смотрите мой ответ: String.Format()с «G» должен получить то, что вы хотите .. я обновил свой ответ со ссылкой на стандартные числовые форматы. Очень удобно.
Уши собаки
3
Десятичная дробь может быть приведена к double, и значение ToStringпо умолчанию для двойного испускает завершающие нули. Прочитайте это
Shimmy Weitzhandler
2
И это, вероятно, будет стоить меньше производительности (в промежутках от очень большого количества записей), чем передача функции G в виде строкового формата ToString.
Шимми Вайцхандлер
4
Вы не должны преобразовывать десятичное число в двойное, оно потеряет значение и может привести к появлению двух неточностей округления.
Кристианп
Ответы:
167
Разве это не так просто, если вход является строкой? Вы можете использовать один из них:
Следите за значениями, такими как 0,000001. Формат G29 представит их в кратчайшем виде, поэтому он переключится на экспоненциальную запись. string.Format("{0:G29}", decimal.Parse("0.00000001",System.Globalization.CultureInfo.GetCultureInfo("en-US")))даст "1E-08" в результате.
Из всех ответов ваши имели меньше всего шагов. Спасибо, Собачьи Уши.
Зо
4
var d = 2,0 м; d.ToString ( "G");
Дэйв Хиллиер,
3
@ Дэйв Хиллиер - я вижу, я исправил свой ответ. Приветствия. [добавлен явный «спецификатор точности»]
Уши собаки
16
Следите за значениями, такими как 0,000001. Формат G29 представит их в кратчайшем виде, поэтому он переключится на экспоненциальную запись. string.Format ("{0: G29}", decimal.Parse ("0.00000001", System.Globalization.CultureInfo.GetCultureInfo ("en-US"))) в результате даст "1E-08"
Конрад,
15
@ Конрад - есть ли способ избежать научного обозначения для чисел, которые имеют 5 или 6 десятичных знаков?
Джилл
202
Я столкнулся с той же проблемой, но в случае, когда у меня нет контроля над выводом в строку, о котором позаботилась библиотека. Изучив детали реализации типа Decimal (см. Http://msdn.microsoft.com/en-us/library/system.decimal.getbits.aspx ), я придумал хитрый трюк (здесь как расширение метод):
Этот ответ является собственностью, потому что в отличие от любого другого ответа на этот вопрос (и даже целого предмета) на самом деле РАБОТАЕТ и выполняет то, что задает ОП.
Coxy
2
Является ли число 0 точным значением здесь или просто для покрытия большинства ожидаемых значений?
Simon_Weaver
3
MSDN гласит: «Коэффициент масштабирования - это неявное число 10, возведенное в степень в диапазоне от 0 до 28», что, как я понимаю, десятичное число будет иметь не более 28 цифр после запятой. Любое количество нулей> = 28 должно работать.
Томас Матерна
2
Это лучший ответ! Число в ответе содержит 34 цифры, за 1которыми следуют 33 0, но это создает точно такой же decimalэкземпляр, как число с 29 цифрами, одной 1и 28-ми 0. Так же, как @ThomasMaterna сказал в своем комментарии. Не System.Decimalможет содержать более 29 цифр (цифры с начальными цифрами больше, чем 79228...могут иметь только 28 цифр). Если вы хотите больше конечных нулей, умножьте на 1.000...mвместо деления. Также Math.Roundможно отрубить несколько нулей, например, Math.Round(27.40000m, 2)дает 27.40m, так что остался только один ноль.
Джеппе Стиг Нильсен
2
Отличный трюк, но он НЕ работает на Mono и не гарантирует работу с функциональными версиями .NET
Это прекрасный ответ. Это очень просто, и вы можете точно видеть, что происходит, вместо того, чтобы использовать магический формататор строк.
Тимоти Гонсалес
9
Хорошо, но это не будет работать для культур, которые используют запятую для десятичного разделителя. Вы должны были бы использоватьCulture.NumberFormat.NumberDecimalSeparator
blearyeye
1
Лучший подход Все остальное излишне сложно. Просто не забывайте всегда проверять, содержит ли ваш номер десятичную точку.
RRM
1
В расширении отсутствует параметр «this» перед параметром: public static string DecimalToString (this decimal dec)
João Antunes
Большое спасибо за комментарии. Я обновил ответ новой версией с советами.
x7BiT
19
Используйте #символ hash ( ), чтобы отображать только завершающие нули, когда это необходимо. Смотрите тесты ниже.
Не ответ Вы не удаляете конечные нули, вы удаляете точность. Ваш предложенный метод num1.ToString("0.##")должен вернуть 13.1534545765(без изменений), потому что нет никаких завершающих нулей.
Ян 'сплит' К.
И именно поэтому я показываю ответы на три предложенных мне ввода, чтобы пользователи могли видеть, как работает мое решение.
Fizzix
Он не отвечает на вопрос, даже если вы перечислите предлагаемые материалы.
Дейв Фридель
2
Я бы проголосовал за это 10 раз, если бы мог. Именно то, что мне было нужно!
SubqueryCrunch
1
Идеальный ответ на вопрос. ЛУЧШИЙ ответ на мой взгляд. Комментарий, что это удаляет точность, является правильным, но это не было вопросом. Самое главное - это то, что мне нужно. Мои пользователи обычно вводят целые числа, возможно, что-то вроде 2,5, но мне нужно поддерживать 3 цифры после запятой. Поэтому я хочу дать им то, что они вошли, а не с кучей нулей, в которые они не вошли. например, Console.Write ($ "num3 = {num3: 0. ##}"); => num3 = 30
Обратите внимание, что если vесть 0m, результатом вашего кода будет пустая строка, а не "0".
Сэм
2
Да. Это должно быть "0. ########".
PRMan
2
Подход очень низкого уровня, но я верю, что это был бы наиболее эффективный способ, используя только быстрые целочисленные вычисления (без медленного анализа строк и чувствительных к культуре методов):
publicstaticdecimalNormalize(thisdecimal d){int[] bits =decimal.GetBits(d);int sign = bits[3]&(1<<31);int exp =(bits[3]>>16)&0x1f;uint a =(uint)bits[2];// Top bitsuint b =(uint)bits[1];// Middle bitsuint c =(uint)bits[0];// Bottom bitswhile(exp >0&&((a %5)*6+(b %5)*6+ c)%10==0){uint r;
a =DivideBy10((uint)0, a,out r);
b =DivideBy10(r, b,out r);
c =DivideBy10(r, c,out r);
exp--;}
bits[0]=(int)c;
bits[1]=(int)b;
bits[2]=(int)a;
bits[3]=(exp <<16)| sign;returnnewdecimal(bits);}privatestaticuintDivideBy10(uint highBits,uint lowBits,outuint remainder){ulong total = highBits;
total <<=32;
total = total |(ulong)lowBits;
remainder =(uint)(total %10L);return(uint)(total /10L);}
@Damien, да, и обратите внимание, что для этих целей (вы ничего не почувствуете, если не сделаете миллиард записей), во-первых, потому что double быстрее, во-вторых, потому что передача формата строки в функцию ToString требует большей производительности, чем не прохождение параметров. Опять же, вы ничего не почувствуете, если не будете работать с миллиардами записей.
Шимми Вайцхандлер
1
Вам не нужно указывать G, потому что double.ToStringпо умолчанию удаляет завершающие нули.
Shimmy Weitzhandler
4
Следите за значениями, такими как 0,000001. Они будут представлены в экспоненциальной записи. double.Parse ("0.00000001", System.Globalization.CultureInfo.GetCultureInfo ("en-US")). ToString () даст в результате "1E-08"
Конрад
17
Никогда не делай этого. Обычно причина, по которой вы используете десятичную дробь, заключается в том, что вы представляете число точно (не примерно так, как двойное число). Конечно, эта ошибка с плавающей запятой, вероятно, довольно мала, но может привести к отображению неправильных чисел, тем не менее
Адам Теген
2
О, преобразование 128-битного типа данных (десятичного) в 64-битный тип данных (double) для форматирования не является хорошей идеей!
Зависит от того, что представляет ваше число и как вы хотите управлять значениями: это валюта, вам нужно округление или усечение, вам нужно это округление только для отображения?
Если для отображения рассмотрим форматирование чисел x.ToString ("")
privatestaticdecimalTrim(thisdecimalvalue){var s =value.ToString(CultureInfo.InvariantCulture);return s.Contains(CultureInfo.InvariantCulture.NumberFormat.NumberDecimalSeparator)?Decimal.Parse(s.TrimEnd('0'),CultureInfo.InvariantCulture):value;}privatestaticdecimal?Trim(thisdecimal?value){returnvalue.HasValue?(decimal?)value.Value.Trim():null;}privatestaticvoidMain(string[] args){Console.WriteLine("=>{0}",1.0000m.Trim());Console.WriteLine("=>{0}",1.000000023000m.Trim());Console.WriteLine("=>{0}",((decimal?)1.000000023000m).Trim());Console.WriteLine("=>{0}",((decimal?)null).Trim());}
(I) -> Разобрать десятичное значение из любого источника строки.
(II) -> Во-первых: приведение к удвоению удаляет завершающие нули. Второе: другие приводятся к десятичному типу, потому что не существует неявного преобразования из десятичного в двойное и наоборот)
Вы принимаете все значения, которые будут соответствовать десятичному, в двойном. Это может вызвать OverflowExeception. Вы также можете потерять точность.
не вариант вообще по сравнению с другими подходами в этом посте. Преобразование в строку и обратно всегда плохой вариант для манипулирования числами (хотя бы из-за локали)
Владимир Семашкин
-11
попробуй вот так
string s ="2.4200";
s = s.TrimStart('0').TrimEnd('0','.');
Вы можете использовать subString()метод для этого, но в соответствии с вопросом, размещенным здесь, я не вижу каких-либо требований, как это =)
Singleton
2
Как насчет локалей, которые не используют '.'
Дэйв Хиллиер,
10
Это с треском проваливается для чисел, которые кратны 10,0.
Бен Фойгт
1
То, что сказал @BenVoigt, совершенно правильно, так как пример "12300.00"будет урезан "123". Другой эффект, который кажется нежелательным, заключается в том, что некоторые числа, подобные "0.00", обрезаются до пустой строки ""(хотя это число является особым случаем целочисленного значения, кратного 10,0).
String.Format()
с «G» должен получить то, что вы хотите .. я обновил свой ответ со ссылкой на стандартные числовые форматы. Очень удобно.double
, и значениеToString
по умолчанию для двойного испускает завершающие нули. Прочитайте этоToString
.Ответы:
Разве это не так просто, если вход является строкой? Вы можете использовать один из них:
Это должно работать для всех входных данных.
Обновление Проверьте стандартные числовые форматы. Мне пришлось явно установить спецификатор точности равным 29, поскольку документы четко указывают:
Обновление Конрада указано в комментариях:
источник
Я столкнулся с той же проблемой, но в случае, когда у меня нет контроля над выводом в строку, о котором позаботилась библиотека. Изучив детали реализации типа Decimal (см. Http://msdn.microsoft.com/en-us/library/system.decimal.getbits.aspx ), я придумал хитрый трюк (здесь как расширение метод):
Экспонента десятичной части сводится к тому, что нужно. Вызов ToString () для выходного десятичного числа запишет число без запаздывания 0. Например
источник
1
которыми следуют 330
, но это создает точно такой жеdecimal
экземпляр, как число с 29 цифрами, одной1
и 28-ми0
. Так же, как @ThomasMaterna сказал в своем комментарии. НеSystem.Decimal
может содержать более 29 цифр (цифры с начальными цифрами больше, чем79228...
могут иметь только 28 цифр). Если вы хотите больше конечных нулей, умножьте на1.000...m
вместо деления. ТакжеMath.Round
можно отрубить несколько нулей, например,Math.Round(27.40000m, 2)
дает27.40m
, так что остался только один ноль.На мой взгляд, безопаснее использовать строки произвольного числового формата .
источник
Я использую этот код, чтобы избежать научной нотации "G29":
РЕДАКТИРОВАТЬ: используя систему CultureInfo.NumberFormat.NumberDecimalSeparator:
источник
Culture.NumberFormat.NumberDecimalSeparator
Используйте
#
символ hash ( ), чтобы отображать только завершающие нули, когда это необходимо. Смотрите тесты ниже.источник
num1.ToString("0.##")
должен вернуть13.1534545765
(без изменений), потому что нет никаких завершающих нулей.Я нашел элегантное решение от http://dobrzanski.net/2009/05/14/c-decimaltostring-and-how-to-get-rid-of-trailing-zeros/
В принципе
источник
v
есть0m
, результатом вашего кода будет пустая строка, а не"0"
.Подход очень низкого уровня, но я верю, что это был бы наиболее эффективный способ, используя только быстрые целочисленные вычисления (без медленного анализа строк и чувствительных к культуре методов):
источник
a
иb
) в каждой итерации , а если они все равны нулю , так или иначе. Однако затем я нашел это удивительно простое решение, которое также легко превосходит то, что мы с вами придумали в отношении производительности .Это будет работать:
Или если ваше начальное значение
string
:Обратите внимание на этот комментарий .
источник
double.ToString
по умолчанию удаляет завершающие нули.Это просто
Проверено.
Ура :)
источник
Зависит от того, что представляет ваше число и как вы хотите управлять значениями: это валюта, вам нужно округление или усечение, вам нужно это округление только для отображения?
Если для отображения рассмотрим форматирование чисел x.ToString ("")
http://msdn.microsoft.com/en-us/library/dwhawy9k.aspx и
http://msdn.microsoft.com/en-us/library/0c899ak8.aspx
Если это просто округление, используйте перегрузку Math.Round, для которой требуется перегрузка MidPointRounding.
http://msdn.microsoft.com/en-us/library/ms131274.aspx )
Если вы получаете свое значение из базы данных, рассмотрите приведение вместо преобразования: double value = (decimal) myRecord ["columnName"];
источник
Вы можете просто установить как:
источник
Если вы хотите сохранить десятичное число, попробуйте следующий пример:
источник
Попытка сделать более дружественное решение DecimalToString ( https://stackoverflow.com/a/34486763/3852139 ):
Вывод:
источник
Очень простой ответ - использовать TrimEnd (). Вот результат,
Выходное значение равно 1 Если мое значение равно 1,01, то выходное значение будет 1,01
источник
value = 100
?Следующий код может быть использован, чтобы не использовать строковый тип:
Возвращает 789,5
источник
Обрезать конечные нули очень просто, решите с помощью дуплексного приведения:
(I) -> Разобрать десятичное значение из любого источника строки.
(II) -> Во-первых: приведение к удвоению удаляет завершающие нули. Второе: другие приводятся к десятичному типу, потому что не существует неявного преобразования из десятичного в двойное и наоборот)
источник
попробуйте этот код:
источник
попробуй вот так
а затем преобразовать это, чтобы плавать
источник
subString()
метод для этого, но в соответствии с вопросом, размещенным здесь, я не вижу каких-либо требований, как это =)"12300.00"
будет урезан"123"
. Другой эффект, который кажется нежелательным, заключается в том, что некоторые числа, подобные"0.00"
, обрезаются до пустой строки""
(хотя это число является особым случаем целочисленного значения, кратного 10,0).