C как double вывести с 2 знаками после запятой
При выводе строк в консоли с помощью метода Console.WriteLine для встраивания значений в строку мы можем применять форматирование вместо конкатенации:
В строке «Имя: <0>Возраст: <1>» на место <0>и <1>затем будут вставляться в порядке следования значения переменныйх name и age
То же самое форматирование в строке мы можем сделать не только в методе Console.WriteLine, но и в любом месте программы с помощью метода string.Format :
Метод Format принимает строку с плейсхолдерами типа <0>, <1>и т.д., а также набор аргументов, которые вставляются на место данных плейсхолдеров. В итоге генерируется новая строка.
Спецификаторы форматирования
В методе Format могут использоваться различные спецификаторы и описатели, которые позволяют настроить вывод данных. Рассмотрим основные описатели. Все используемые форматы:
Задает формат денежной единицы, указывает количество десятичных разрядов после запятой
Целочисленный формат, указывает минимальное количество цифр
Экспоненциальное представление числа, указывает количество десятичных разрядов после запятой
Формат дробных чисел с фиксированной точкой, указывает количество десятичных разрядов после запятой
Задает более короткий из двух форматов: F или E
Также задает формат дробных чисел с фиксированной точкой, определяет количество разрядов после запятой
Задает отображения знака процентов рядом с число, указывает количество десятичных разрядов после запятой
Шестнадцатеричный формат числа
Форматирование валюты
Для форматирования валюты используется описатель «C»:
Число после описателя указывает, сколько чисел будет использоваться после разделителя между целой и дробной частью. При выводе также добавляется обозначение денежного знака для текущей культуры компьютера. В зависимости от локализации текущей операционной системы результат может различаться. Также обратите внимание на округление в первом примере.
Форматирование целых чисел
Для форматирования целочисленных значение применяется описатель «d»:
Число после описателя указывает, сколько цифр будет в числовом значении. Если в исходном числе цифр меньше, то к нему добавляются нули.
Форматирование дробных чисел
Для форматирования дробны чисел используется описатель F, число после которого указывает, сколько знаков будет использоваться после разделителя между целой и дробной частью. Если исходное число — целое, то к нему добавляются разделитель и нули.
Формат процентов
Описатель «P» задает отображение процентов. Используемый с ним числовой спецификатор указывает, сколько знаков будет после запятой:
Настраиваемые форматы
Используя знак #, можно настроить формат вывода. Например, нам надо вывести некоторое число в формате телефона +х (ххх)ххх-хх-хх:
Метод ToString
Метод ToString() не только получает строковое описание объекта, но и может осуществлять форматирование. Он поддерживает те же описатели, что используются в методе Format:
Интерполяция строк
Интерполяция строк призвана упростить форматирование строк. Так, перепишем пример с выводом значений переменных в строке:
Знак доллара перед строкой указывает, что будет осуществляться интерполяция строк. Внутри строки опять же используются плейсхолдеры <. >, только внутри фигурных скобок уже можно напрямую писать те выражения, которые мы хотим вывести.
Интерполяция по сути представляет более лаконичное форматирование. При этом внутри фигурных скобок мы можем указывать не только свойства, но и различные выражения языка C#:
Также внутри фигурных скобок можно выполнять более сложные выражения, например, вызывать методы:
Уже внутри строки можно применять форматирование. В этом случае мы можем применять все те же описатели, что и в методе Format . Например, выведем номер телефона в формате +x xxx-xxx-xx-xx:
Округление числа до 2 десятичных знаков в C
Как я могу объединить float (например, 37.777779) до двух знаков после запятой (37.78) в C?
16 ответов
Если вы просто хотите округлить число для целей вывода, то строка формата «%.2f» действительно является правильным ответом. Однако, если вы действительно хотите округлить значение с плавающей запятой для дальнейших вычислений, выполните следующие действия:
Обратите внимание, что вы можете выбрать три разных правила округления: округлить (т.е. усечь после двух знаков после запятой), округлить до ближайшего и округлить. Обычно вы хотите округлить до ближайшего.
Как отмечали некоторые другие, из-за особенностей представления с плавающей запятой эти округленные значения могут быть не совсем «очевидными» десятичными значениями, но они будут очень близки.
Для большей (много!) дополнительной информации о округлении, и особенно о правилах развязывания для округления до ближайшего, см. статью Википедии об округлении.
Предполагая, что вы говорите о значении для печати, тогда Andrew Coleson и AraK ответят правильно:
Но обратите внимание, что если вы хотите округлить число до 37.78 для внутреннего использования (например, для сравнения с другим значением), то это не очень хорошая идея из-за того, как работают числа с плавающей точкой: вы обычно не хотите выполнять сравнения равенств для с плавающей запятой, вместо этого используйте целевое значение +/- значение сигмы. Или кодируйте число как строку с известной точностью и сравните это.
См. ссылку в Greg Hewgill ответьте на соответствующий вопрос, в котором также рассказывается, почему вы не должны использовать с плавающей точкой для финансовых расчетов.
Как насчет этого:
Если вы хотите записать в C-строку:
Не существует способа округлить float до другого float , потому что округленный float может быть не представимым (ограничение числа с плавающей запятой). Например, скажите, что вы округлены с 37.777779 по 37.78, но ближайший представимый номер равен 37.781.
Тем не менее, вы можете «закруглить» float с помощью строковой функции формата.
Кроме того, если вы используете С++, вы можете просто создать такую функцию:
Затем вы можете вывести любое двойное myDouble с n местами после десятичной точки с кодом, например:
Вы все еще можете использовать:
В С++ (или в C с приложением C-стиля) вы можете создать функцию:
Тогда std::cout << showDecimals(37.777779,2); произведет: 37.78.
Очевидно, вам не нужно создавать все 5 переменных в этой функции, но я оставляю их там, чтобы вы могли видеть логику. Есть, вероятно, более простые решения, но это хорошо работает для меня, тем более что это позволяет мне корректировать количество цифр после десятичной точки по мере необходимости.
Используйте float roundf(float x) .
«Круглые функции округляют свой аргумент до ближайшего целочисленного значения в формате с плавающей запятой, округляя половину случаев от нуля, независимо от текущего направления округления.» C11dr §7.12.9.5
В зависимости от вашей реализации float числа, которые могут показаться на полпути, не являются. поскольку плавающая точка обычно ориентирована на базу 2. Более того, точное округление до ближайшего 0.01 во всех случаях «на полпути» является наиболее сложным.
Хотя «1.115» «на полпути» между 1.11 и 1.12, при преобразовании в float значение 1.115000009537. и больше не «на полпути» , но ближе к 1.12 и раундам ближе к ближайшему float of 1.120000004768.
«1.125» — «на полпути» между 1.12 и 1.13, при преобразовании в float значение равно 1.125 и является «на полпути» . Он округляется к 1.13 из-за связей с четным правилом и раундами до ближайшего float от 1.129999995232.
Хотя «1.135» «на полпути» между 1.13 и 1.14, при преобразовании в float значение 1.134999990463. и больше не «на полпути» , а ближе к 1.13 и раундам ближе к ближайшему float of 1.129999995232.
Если используется код
Хотя «1.135» — «на полпути» между 1.13 и 1.14, при преобразовании в float значение 1.134999990463. и больше не «на полпути» , а ближе к 1.13, а неправильно до float из 1.139999985695. из-за более ограниченной точности float vs. double . Это неправильное значение может считаться правильным, в зависимости от целей кодирования.
Здесь n — число десятичных знаков
Я сделал этот макрос для округления чисел с плавающей точкой. Добавьте это в свой заголовок/существо файла
Определение кода:
Результаты:
Позвольте мне сначала попытаться оправдать мою причину добавления еще одного ответа на этот вопрос. В идеальном мире округление на самом деле не имеет большого значения. Однако в реальных системах вам может потребоваться несколько проблем, которые могут привести к округлению, что может и не быть тем, что вы ожидаете. Например, вы можете выполнять финансовые расчеты, когда конечные результаты округляются и отображаются пользователям как 2 десятичных знака; эти же значения хранятся с фиксированной точностью в базе данных, которая может содержать более двух знаков после запятой (по разным причинам, нет оптимального количества мест для хранения. зависит от конкретных ситуаций, которые должна поддерживать каждая система, например, крошечных предметов, чьи цены представляют собой доли копейки за единицу); и вычисления с плавающей запятой выполняются с значениями, где результаты равны плюс/минус эпсилон. Я столкнулся с этими проблемами и развивал свою собственную стратегию на протяжении многих лет. Я не буду утверждать, что я столкнулся со всеми сценариями или получил лучший ответ, но ниже приведен пример моего подхода, который преодолевает эти проблемы:
Предположим, что 6 десятичных знаков считаются достаточной точностью для вычислений по поплавкам/удвоениям (произвольное решение для конкретного приложения) с использованием следующей функции/метода округления:
Округление до 2 десятичных знаков для представления результата может быть выполнено как:
Для val = 6.825 результат 6.83 , как ожидалось.
Для val = 6.824999 результат 6.82 . Здесь предположение состоит в том, что расчет привел в точности к 6.824999 , а седьмое десятичное число — нулю.
Для val = 6.8249999 результат 6.83 . 7-е число после запятой 9 в этом случае заставляет функцию Round(val,6) дать ожидаемый результат. Для этого случая может быть любое количество конечных 9 s.
Для val = 6.824999499999 результат 6.83 . Округление до восьмого десятичного знака в качестве первого шага, т.е. Round(val,8) , заботится о одном неприятном случае, когда вычисляемый результат с плавающей запятой вычисляется до 6.8249995 , но внутренне представлен как 6.824999499999. .
Наконец, пример из вопроса. val = 37.777779 приводит к 37.78 .
Этот подход может быть далее обобщен как:
где N — точность, которая должна поддерживаться для всех промежуточных вычислений по поплавкам/удвоениям. Это работает и с отрицательными значениями. Я не знаю, является ли этот подход математически правильным для всех возможностей.
Как ограничить значение с плавающей запятой только двумя знаками после десятичной точки в C?
Как округлить значение с плавающей запятой (например, 37.777779) до двух десятичных знаков (37.78) в C?
Само число правильно округлить нельзя, потому что float (И double ) не являются десятичными числами с плавающей запятой — они являются двоичными с плавающей запятой, поэтому округление до десятичных разрядов бессмысленно. Однако вы можете округлить результат. — Pavel Minaev
Это не бессмысленно; это неточно. Есть большая разница. — Brooks Moses
Какого округления вы ожидаете? Половина вверх или округление до ближайшего четного? — Truthseeker Rangwan
17 ответы
Если вы просто хотите округлить число для целей вывода, тогда «%.2f» строка формата действительно правильный ответ. Однако, если вы действительно хотите округлить значение с плавающей запятой для дальнейших вычислений, работает примерно следующее:
Обратите внимание, что есть три различных правила округления, которые вы, возможно, захотите выбрать: округление в меньшую сторону (т. Е. Усечение после двух десятичных знаков), округление до ближайшего и округление в большую сторону. Обычно вам нужно округлить до ближайшего.
Как отмечали некоторые другие, из-за особенностей представления с плавающей запятой эти округленные значения могут быть не совсем «очевидными» десятичными значениями, но они будут очень близкими.
Для получения гораздо (гораздо!) Дополнительной информации об округлении, и особенно о правилах ограничения связи для округления до ближайшего, см. статья в Википедии об округлении.
ответ дан 03 авг.
Можно ли изменить его для поддержки округления до произвольной точности? — user472308
@slater Когда вы говорите «произвольная точность», вы спрашиваете об округлении, например, до трех вместо двух десятичных знаков, или об использовании библиотек, которые реализуют десятичные значения с неограниченной точностью? В первом случае внесите, как я надеюсь, очевидную корректировку к константе 100; в противном случае выполните точно такие же вычисления, как показано выше, только с той библиотекой с множественной точностью, которую вы используете. — Дейл Хагглунд
@DaleHagglung Первый, спасибо. Корректировка заменяет 100 на pow (10, (int) desirePrecision)? — user472308
Ага. Чтобы округлить после k десятичных знаков, используйте масштабный коэффициент 10 ^ k. Это должно быть очень легко увидеть, если вы выпишете несколько десятичных значений вручную и поиграете с числами, кратными 10. Предположим, вы работаете со значением 1.23456789 и хотите округлить его до трех знаков после запятой. Вам доступна операция округлить до целого числа. Итак, как переместить первые три десятичных знака так, чтобы они оставались слева от десятичной точки? Надеюсь, понятно, что вы умножаете на 10 ^ 3. Теперь вы можете округлить это значение до целого числа. Затем вы возвращаете три младшие цифры, разделив их на 10 ^ 3. — Дейл Хагглунд
Могу ли я заставить это работать с doubles тоже как-нибудь? Похоже, не выполняет ту работу, которую я хочу 🙁 (используя floor и ceil ). — Мисс никто
. % .2f в printf. Он печатает только 2 десятичные точки.
Создан 01 июля ’19, 09:07
Этот способ лучше, потому что нет потери точности. — Альбер
@albert Это также имеет то преимущество, что float диапазон как val * 100 может переполниться. — chux — восстановить Монику
Предполагая, что вы говорите о стоимости печати, тогда Эндрю Колесон и Аракответ правильный:
Но обратите внимание, что если вы стремитесь округлить число до 37.78 для внутреннего использования (например, для сравнения с другим значением), тогда это не очень хорошая идея из-за того, как работают числа с плавающей запятой: обычно вы этого не делаете. хотите выполнить сравнение на равенство для чисел с плавающей запятой, вместо этого используйте целевое значение +/- значение сигмы. Или закодируйте число как строку с известной точностью и сравните это.
См. Ссылку в Грег Хьюгилл отвечает на связанный вопрос, который также объясняет, почему вы не должны использовать плавающую точку для финансовых расчетов.
ответ дан 23 мая ’17, 13:05
Проголосовали за решение вопроса, который может быть причиной вопроса (или вопроса, который должен был стоять за вопросом!). Это довольно важный момент. — Брукс Моисей
На самом деле 37.78 можно представить именно с плавающей точкой. Поплавок имеет от 11 до 12 цифр для точности. Этого должно быть достаточно для адреса 3778 377.8 или всех четырех десятичных цифр. — Анонимный Белый
@HaryantoCiu, честно говоря, я немного отредактировал свой ответ. — Джон Картер
динамическая точность: printf(«%.*f», (int)precision, (double)number); — Минхас Камаль
Как насчет этого:
ответ дан 28 авг.
-1: а) это не сработает для отрицательных чисел (хорошо, пример положительный, но все же). б) вы не упоминаете, что невозможно сохранить точное десятичное значение в float — Джон Картер
@therefromhere: (a) Вы правы (b) Что это? Тест в старшей школе? — Daniil
почему вы добавили 0.5? — Мухаммад Тайяб
Необходимо соблюдать правила округления. — Daniil
правила округления в контексте комментария @Daniil являются круглый до ближайшего — Шмиль Кот
Если вы хотите писать в C-строку:
ответ дан 28 авг.
@Sinan: Почему редактирование? @AraK: Нет, являетесь следует позаботиться о размере :). Используйте snprintf (). — AIB
@aib: я бы предположил, потому что / ** / — это комментарии в стиле C, а вопрос помечен для C — Майкл Харен
В C89 разрешен только стиль / ** /, в C99 введена поддержка стиля //. Используйте неработающий / старый компилятор (или включите режим C89), и вы не сможете использовать //-стиль. Сказав это, сейчас 2009 год, давайте рассмотрим их как в стиле C, так и в стиле C ++. — Эндрю Колесон
Невозможно обойти float другому float потому что округлый float может не быть представимым (ограничение чисел с плавающей запятой). Например, вы округлили 37.777779 до 37.78, но ближайшее представимое число — 37.781.
Тем не менее, может «круглый» float с помощью функции строки формата.
ответ дан 27 авг.
Это ничем не отличается от высказывания «нет способа разделить два числа с плавающей запятой и получить одно число, потому что разделенный результат может быть непредставимым», что может быть в точности верным, но не имеет значения. Поплавки всегда неточны, даже для таких простых вещей, как добавление; всегда предполагается, что на самом деле вы получаете «число с плавающей запятой, которое наиболее точно соответствует точному округленному ответу». — Брукс Моисей
Я имел в виду, что вы не можете обойти float до n десятичных знаков, а затем ожидайте, что результат всегда будет иметь n десятичных знаков. Вы все равно получите float , просто не тот, которого вы ожидали. — Эндрю Китон
Кроме того, если вы используете C ++, вы можете просто создать такую функцию:
Затем вы можете вывести любой двойной myDouble с n ставит после десятичной точки с таким кодом:
ответ дан 23 авг.
Вы все еще можете использовать:
ответ дан 28 авг.
Это усекает до десятичной точки (то есть даст 37), и ему нужно округлить до двух разрядов. после десятичная точка. — Павел Минаев
Однако округление до двух знаков после десятичной точки является тривиальным вариантом (но все же следует упомянуть в ответе; ZeroCool, хотите добавить правку?): Float roundedValue = ceilf (valueToRound * 100.0) / 100.0; — Брукс Моисей
Почему это решение не пользуется большей популярностью? Это работает именно так, как и должно быть с минимальным кодом. Есть ли с этим предостережение? — Энди
В C ++ (или в C с приведением типов в стиле C) вы можете создать функцию:
Затем std::cout << showDecimals(37.777779,2); произведет: 37.78.
Очевидно, что вам действительно не нужно создавать все 5 переменных в этой функции, но я оставлю их там, чтобы вы могли увидеть логику. Вероятно, есть более простые решения, но для меня это хорошо работает — тем более, что оно позволяет мне регулировать количество цифр после десятичного разряда по мере необходимости.
ответ дан 21 авг.
Всегда используйте printf семейство функций для этого. Даже если вы хотите получить значение в виде числа с плавающей запятой, лучше всего использовать snprintf чтобы получить округленное значение в виде строки, а затем проанализировать его с помощью atof :
Я говорю это, потому что подход, показанный на данный момент самый популярный ответ и несколько других здесь — умножение на 100, округление до ближайшего целого числа, а затем снова деление на 100 — ошибочны по двум причинам:
- Для некоторых значений он будет округляться в неправильном направлении, потому что умножение на 100 изменяет десятичную цифру, определяющую направление округления, с 4 на 5 или наоборот из-за неточности чисел с плавающей запятой.
- Для некоторых значений умножение и последующее деление на 100 не выполняет двустороннего действия, а это означает, что даже если округление не выполняется, конечный результат будет неверным.
Чтобы проиллюстрировать первый тип ошибки — иногда неправильное направление округления — попробуйте запустить эту программу:
Вы увидите этот вывод:
Обратите внимание, что значение, с которого мы начали, было меньше 0.015, поэтому математически правильный ответ при округлении до двух знаков после запятой — 2. Конечно, 0.01 — это не так. точно, можно представить как двойное, но мы ожидаем, что наш результат будет двойным, ближайшим к 0.01. С использованием snprintf дает нам этот результат, но используя round(100 * x) / 100 дает нам 0.02, что неверно. Почему? Потому что 100 * x дает нам в результате ровно 1.5. Таким образом, умножение на 100 изменяет правильное направление округления.
Чтобы проиллюстрировать второй вид ошибки — результат иногда бывает неверным из-за * 100 и / 100 не будучи на самом деле противоположными друг другу — мы можем проделать подобное упражнение с очень большим числом:
У нашего числа теперь нет даже дробной части; это целочисленное значение, просто сохраненное с типом double . Значит, результат после округления должен быть тем же самым числом, с которого мы начали, верно?
Если вы запустите указанную выше программу, вы увидите:
Ой. Наш snprintf метод снова возвращает правильный результат, но подход «умножить, затем округлить, затем разделить» не работает. Это потому, что математически правильное значение 8631192423766613.0 * 100 , 863119242376661300.0 , нельзя точно представить в виде двойника; ближайшее значение 863119242376661248.0 . Когда вы разделите это на 100, вы получите 8631192423766612.0 — номер, отличный от того, с которого вы начали.
Надеюсь, это достаточная демонстрация того, что использование roundf для округления до числа десятичных знаков не работает, и что вы должны использовать snprintf вместо. Если вам кажется, что это ужасный хакер, возможно, вы будете уверены в том, что это в основном то, что делает CPython.
+1 за конкретный пример того, что идет не так с моим ответом и аналогичными ему, благодаря странности с плавающей запятой IEEE и предоставлению простой альтернативы. Довольно давно я периферийно осознавал, как много усилий было вложено в печать, и, как мне кажется, они безопасны для циклических значений с плавающей запятой. Я предполагаю, что проделанная тогда работа может появиться здесь. — Дейл Хагглунд
Кхм . Извините за слово салат в конце, которое уже слишком поздно редактировать. Я хотел сказать: «. приложили много усилий, чтобы printf и друзья сделали их безопасными . » — Дейл Хагглунд
Используйте float roundf(float x) .
«Функции round округляют свой аргумент до ближайшего целочисленного значения в формате с плавающей запятой, округляя на полпути от нуля, независимо от текущего направления округления». C11dr §7.12.9.5
В зависимости от вашего float реализации, цифры, которые могут показаться неполными, таковыми не являются. поскольку числа с плавающей запятой обычно ориентированы на основание 2. Далее с точным округлением до ближайшего 0.01 по всем «половинчатым» делам это самая сложная задача.
Хотя «1.115» находится на полпути между 1.11 и 1.12, при преобразовании в float , значение 1.115000009537. и уже не «на полпути», а ближе к 1.12 и раундам к ближайшему float of 1.120000004768.
«1.125» — это «половина пути» между 1.12 и 1.13 при преобразовании в float , значение точно 1.125 и находится «на полпути». Он округляется до 1.13 из-за связи с четным правилом и округляется до ближайшего. float of 1.129999995232.
Хотя «1.135» находится на полпути между 1.13 и 1.14, при преобразовании в float , значение 1.134999990463. и уже не «на полпути», а ближе к 1.13 и раундам к ближайшему float of 1.129999995232.
Если используется код
Хотя «1.135» находится на полпути между 1.13 и 1.14, при преобразовании в float , значение 1.134999990463. и уже не «на полпути», а ближе к 1.13, но неверно раунды в float of 1.139999985695. из-за более ограниченной точности float против double . Это неправильное значение может рассматриваться как правильное, в зависимости от целей кодирования.
ответ дан 03 авг.

Ссылка на n это количество десятичных знаков
ответ дан 16 апр.
-1 по четырем причинам: 1) отсутствие объяснения, 2) уязвимость к переполнению буфера — это приведет к переполнению и, следовательно, вполне возможно, что произойдет сбой, если dval огромный 3) странный if / else блок, в котором вы делаете одно и то же в каждой ветке, и 4) чрезмерно сложное использование sprintf построить спецификатор формата на секунду sprintf вызов; проще просто использовать .* и передайте двойное значение и количество десятичных знаков в качестве аргументов тому же sprintf вызов. — Марк Эмери
Я сделал этот макрос для округления чисел с плавающей запятой. Добавьте его в свой заголовок / файл
ответ дан 17 мар ’18, в 15:03

Это усекает, но вопрос требует округления. Кроме того, он подвержен ошибкам округления в операциях с плавающей запятой. — Эрик Постпищил
Определение кода:
Результаты:

Позвольте мне сначала попытаться обосновать причину, по которой я добавил еще один ответ на этот вопрос. В идеальном мире округление не имеет большого значения. Однако в реальных системах вам может потребоваться столкнуться с несколькими проблемами, которые могут привести к тому, что округление может оказаться не таким, как вы ожидаете. Например, вы можете выполнять финансовые расчеты, в которых окончательные результаты округляются и отображаются пользователям в виде двух знаков после запятой; эти же значения хранятся с фиксированной точностью в базе данных, которая может включать более двух знаков после запятой (по разным причинам; нет оптимального количества мест для хранения . зависит от конкретных ситуаций, которые должна поддерживать каждая система, например, крошечные предметы, цены на которые доли копейки за единицу); и вычисления с плавающей запятой, выполняемые для значений, результаты которых равны плюс / минус эпсилон. На протяжении многих лет я сталкивался с этими проблемами и вырабатывал свою собственную стратегию. Я не буду утверждать, что сталкивался со всеми сценариями или у меня есть лучший ответ, но ниже приведен пример моего подхода, который преодолевает эти проблемы:
Предположим, что 6 десятичных знаков считаются достаточной точностью для вычислений с плавающей запятой / двойным числом (произвольное решение для конкретного приложения) с использованием следующей функции / метода округления:
Округление до двух знаков после запятой для представления результата может быть выполнено как:
Если вы val = 6.825 , результат 6.83 как и ожидалось.
Если вы val = 6.824999 , результат 6.82 . Здесь предполагается, что расчет дал ровно 6.824999 а седьмой десятичный знак равен нулю.
Если вы val = 6.8249999 , результат 6.83 . Седьмой знак после запятой 9 в этом случае вызывает Round(val,6) функция, чтобы дать ожидаемый результат. В этом случае может быть любое количество конечных 9 s.
Если вы val = 6.824999499999 , результат 6.83 . Округление до восьмого знака после запятой в качестве первого шага, т. Е. Round(val,8) , заботится об одном неприятном случае, когда вычисленный результат с плавающей запятой вычисляется как 6.8249995 , но внутренне представлен как 6.824999499999. .
Наконец, пример из вопроса . val = 37.777779 приводит к 37.78 .
Этот подход можно обобщить следующим образом:
где N — точность, которую необходимо поддерживать для всех промежуточных вычислений с плавающей запятой / двойным. Это также работает с отрицательными значениями. Я не знаю, верен ли этот подход математически для всех возможностей.
Форматированный вывод в C#

статьи
Значит, дело было так. Я писал программу на C#, в которой обрабатывалась матрица вещественных чисел, а затем выводилась в консоль. И все бы ничего, однако возникла одна проблема — вывод матрицы был просто ужасен, в том плане, что каждый элемент содержал разное количество символов, да и к тому же, количество символов, я Вам скажу, было немало. Решение данной проблемы я стал искать в Интернете. И вот, спустя некоторое время и посетив несколько сайтов, я нашел замечательную статью, под названием «String Format for Double [C#]» на сайте csharp-examples.net. Так как этот сайт полностью на английском языке, и мне очень понравилась эта статья, то я решил ее перевести.
Начнем!
В следующих примерах показано, как переводить вещественные числа в строку в C#. Для этого Вы можете использовать статический метод String.Format или методы экземпляров double.ToString и float.ToString.
Цифры после точки
В этом примере демонстрируется перевод вещественного числа в строку с фиксированным числом десятичных знаков. Например, для двух знаков используется шаблон «0.00». Если вещественное число содержит менее десятичных знаков, то оставшиеся позиции справа заполняются нулями, если же число знаков больше — производится округление.
Для получения строки с переменным количеством знаков используется символ «#». Чтобы на выходе получить строку, в которой количество десятичных знаков будет не более двух, используйте шаблон «0.##».
Цифры перед точкой
Если на выходе нужно получить строку, в которой число знаков перед точкой будет не менее заданного числа, используйте шаблон, в котором указывается столько нулей перед точкой, сколько символов должно быть минимально.
Разделитель тысяч
Чтобы в строках явно отделять тысячи, к обычному шаблону слева добавляется «0,» (ноль с запятой). К примеру, шаблон «0,0.0» позволяет получить строку, в которой явно отделяются тысячи, а число символов после точки будет не более одного.
Ведущие Нули
Вещественные числа, не превосходящие единицы по абсолютному значению, можно форматировать двумя способами:
- с ведущими нулями
- без ведущих нулей
Случай с ведущими нулями — самый обычный. Для него используются те же шаблоны, что описаны выше.
Чтобы получать строки без ведущих нулей, используется символ «#» перед точкой. Например, по шаблону «#.0» получим строки вида «.5», «123.5».
Выравнивание с помощью пробелов
Для выравнивания числа по правому краю используется запятая перед двоеточием. То есть, ставится запятая, а следом идет число, которое указывает, сколько пробелов должно быть. Пример: «0,10:0.0″.
Для выравнивания по левому краю, шаблон будет таким же, за исключением того, что число пробелов должно быть указано со знаком минуса.
P.S. Этот способ можно использовать только с помощью метода String.Format
Пользовательское форматирование отрицательных чисел и нулей
Если Вам необходимо получить строки в своем стиле форматирования, используйте точку с запятой для разделения шаблона на три части. Первая часть отвечает за форматирование положительных чисел, вторая — отрицательных, третья — нулей. Если Вы пропустите последнюю часть, то нули будут отформатированы так же, как и положительные числа.
Некоторые забавные примеры
Как Вы могли заметить в предыдущем примере, Вы можете вставить любой текст в шаблон, например, «my text 0.0″. Вы даже можете вставить текст между нулями: «0aaa.bbb0″.
Небольшое мое дополнение к статье
В зависимости от локали (языкового стандарта программы), выводимые символы могут отличаться. Например, вместо точек выводятся запятые и т.д. К слову, у меня вместо десятичной точки выводится запятая, а вместо тысячного разделителя — пробел.