Перейти к содержимому

Как округлить число в с

  • автор:

Как округлять числа в языке С до целых в заданную сторону?

Как округлять действительные числа в языке С до ближайших целых, если нужно: 1) Округлить до ближайшего целого числа в любую сторону 2) Округлить до ближайшего целого числа в меньшую сторону 3) Округлить до ближайшего целого числа в большую сторону Тип данных double Вопрос решён, спасибо

Отслеживать
задан 28 дек 2016 в 10:10
257 1 1 золотой знак 3 3 серебряных знака 15 15 бронзовых знаков
Э. floor() , ceil() , ronud() чем не устроили?
28 дек 2016 в 10:15
Если решён, пометьте правильный ответ.
28 дек 2016 в 23:18

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

  • функция ceil — округление вверх
  • функция floor — округление вниз
  • функция rint — округляет к ближайшему целому (при default rounding mode)
  • преобразование типа к целому — отбрасывание дробной части

Отслеживать
ответ дан 28 дек 2016 в 10:17
Mikhail Vaysman Mikhail Vaysman
14.2k 1 1 золотой знак 21 21 серебряный знак 31 31 бронзовый знак
Отбрасывание дробной части не равно Округлить до ближайшего целого.
28 дек 2016 в 10:18
@PinkTux согласен. уточнил ответ — добавил rint. спасибо.
28 дек 2016 в 10:26

    Важное на Мете
Похожие

Подписаться на ленту

Лента вопроса

Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.

Дизайн сайта / логотип © 2024 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2024.1.3.2953

Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.

Учимся округлять в C#

А знаете ли вы, что Math.Round(1.5) == Math.Round(2.5) == 2 ? Можете ли сходу сказать, сколько будет -7%3 и 7%-3 ? Помните ли, чем отличаются Math.Round , Math.Floor , Math.Ceiling , Math.Truncate ? А как происходит округление при использовании string.Format ? Давайте немного погрузимся в мир округлений и разберёмся с нюансами, которые не для всех могут быть очевидными.

Math.Round

 Math.Round — это метод округления к ближайшему числу или к ближайшему числу с заданным количеством знаков после запятой. Работает с типами decimal и double , в параметрах можно встретить три вида параметров:
  • value : округляемое число
  • digits : количество знаков в дробной части, которые нужно оставить
  • mode : параметр, который определяет в какую сторону округлять число, которое находится ровно посередине между двумя вариантами

Параметр mode используется, когда округляемое значение находится ровно посередине между двумя вариантами. Принимает значение из следующего перечисления:

Обратите внимание, что по умолчанию mode == MidpointRounding.ToEven , поэтому Math.Round(1.5) == Math.Round(2.5) == 2 .

Math.Floor, Math.Ceiling, Math.Truncate

Сводная таблица

Сориентироваться в методах округления может помочь следующая табличка:

Округление проводится в соответствии со стандартом IEEE Standard 754, section 4.

Целочисленное деление и взятие по модулю

В C# есть два замечательных оператора над целыми числами: / для целочисленного деления (MSDN) и % для взятия остатка от деления (MSDN). Деление производится по следующим правилам:

  • При целочисленном делении результат всегда округляется по направлению к нулю.
  • При взятии остатка от деления должно выполняться следующее правило: x % y = x – (x / y) * y

Также можно пользоваться шпаргалкой:

string.Format

При форматировании чисел в виде строки можно пользоваться функцией string.Format (см. Standard Numeric Format Strings, Custom Numeric Format Strings). Например, для вывода числа с двумя знаками после десятичной точки можно воспользоваться string.Format(«», value) или string.Format(«», value) . Округление происходит по принципу AwayFromZero . Проиллюстрируем правила округления очередной табличкой:

", value) |       

Задачи

На приведённую тему есть две задачки в ProblemBook.NET: Rounding1, Rounding2.

  • GitHub
  • Twitter
  • RSS

Округление к целому в .NET

Все мы знаем, что такое округление. Если кто-то забыл, то округление — это замена числа на его приближённое значение, записанное с меньшим количеством значащих цифр. Если спросить человека с ходу, что получится при округлении 6,5 до целых, он не задумываясь ответит «7». Нас со школы учили, что числа округляются до ближайшего целого большего по модулю числа. То есть, если в округляемом числе дробная часть равна или больше половине разряда целой части, то мы округляем исходное число до ближайшего большего.

6,4 = 6 6,5 = 7 6,6 = 7

И вот, выходя из школы и становясь программистами мы зачастую ожидаем того же поведения от наших мощных языков программирования. Совсем забывая, что в школе нас учили «математическому округлению», а на самом деле видов этих округлений намного больше. На одной только википедии можно нарыть вот сколько вариантов округления 0,5 к ближайшему целому числу:

  • Математическое округление
  • Случайное округление
  • Чередующееся округление
  • Банковское округление

А вот «банковское округление» — это уже интересненько. «Почему?» — спросите вы. В дотнете мы часто используем класс Convert, который предоставляет уйму методов для конвертации одного типа данных в другие (не путать с приведением, о нем будет ниже). И вот, оказывается, что при конвертации чисел с плавающей запятой (double, float, decimal) в целочисленный тип int через метод Convert.ToInt32 под капотом работает «банковское» округление. Оно тут используется по умолчанию!

И вроде как незнание этой мелочи сильно не сказывается на вашей работе, но как только вам приходится работать со статистикой и расчетами показателей, базирующихся на куче всяких записей и циферок эта штука вылазит боком. Потому что мы ожидаем (от незнания), что все наши конвертации\округления в расчетах будут работать по правилам «математического» округления. И смотрим как баран на новые ворота на результат округления 6,5, который равен 6.

Первая мысль программиста, который это видит — «Возможно округление работает в обратную сторону, и по правилам округляется до наименьшего числа?», «Может я что-то забыл из школьной математики?». Дальше он идет в google и понимает что, ничего не забыли, и что творится какая-то чернь. На этом шаге ленивый разработчик решит, что это стандартное поведение метода Convert.ToInt32, округлять до наименьшего целого, и забьет на дальнейший поиск. И будет думать, что если Convert.ToInt32(6,5) = 6, то по аналогии Convert.ToInt32(7,5) = 7. Но не тут-то было. Таких разработчиков в дальнейшем судьба бьет по голове пачкой багов от отдела QA.

Дело в том, что «банковское» округление работает чуть хитрее — оно округляет число до ближайшего четного целого числа, а не до ближайшего целого по модулю. Этот тип округления якобы более честный в случае применения в банковских операциях — банки не будут обделять ни себя ни клиентов, из расчета, что операций с четной целой частью, сколько же, сколько и операций с нечетной целой частью. Но как по мне — всё равно мутновато 🙂 Так вот, именно поэтому Convert.ToInt32(6,5) даст результат 6, а результат для Convert.ToInt32(7,5) будет равен 8, а не 7 🙂

Что же делать, что бы получить всем привычное «математическое» округления? У методов класса Convert нет дополнительных настроек округления. Оно и верно, ибо класс этот служит в первую очередь не для округления, а для конвертации типов. На помощь нам приходит замечательный класс Math с его методом Round. Но тут тоже будьте аккуратны, ибо по умолчанию этот метод работает так же как и округление в Convert.ToInt32() — по «банковскому» правилу. Однако, это поведение можно изменять с помощью второго аргумента, входящего в метод Round. Так, Math.Round(someNumber, MidpointRounding.ToEven) даст нам дефолтовое «банковское» округление. А вот Math.Round(someNumber, MidpointRounding.AwayFromZero) будет работать по привычным правилам «математического» округления.

И кстати, Convert.ToInt32() не использует под капотом System.Math.Round(). Специально нарыл на github реализацию этого метода — округление считается по остаткам:

public static int ToInt32(double value) < if (value >= 0) < if (value < 2147483647.5) < int result = (int)value; double dif = value - result; if (dif >0.5 || dif == 0.5 && (result & 1) != 0) result++; return result; > > else < if (value >= -2147483648.5) < int result = (int)value; double dif = value - result; if (dif < -0.5 || dif == -0.5 && (result & 1) != 0) result--; return result; >> throw new OverflowException(Environment.GetResourceString("Overflow_Int32")); > 

И напоследок пару слов о приведении типов:

var number = 6.9; var intNumber = (int)number; 

В этом примере я привожу тип с плавающей запятой (double в данном случае) к целочисленному int. Так вот, при приведении типов к целочисленному вся не целая часть просто отсекается. Соответственно, в данном примере в переменной «intNumber» будет лежать число 6. Никаких правил округления тут нет, просто отсечение всего, что идет после запятой. Помните об этом!

  • Про округление на wikipedia
  • Про проблему конвертации
  • Про округление Math.Round
  • Реализация Convert.ToInt32

P.P.S. Кстати, в python округление по дефолту работает так же по «банковскому» принципу. Возможно, в вашем языке такая же штука, будьте бдительны с числами 🙂

ceil в C/C++: округление вверх

�� Привет! В этой статье мы поговорим о функции ceil . Эта функция позволяет нам округлить число вверх в C/C++. Сначала мы посмотрим как использовать эту функцию на примере, а потом попробуем реализовать ее сами. Также мы разберемся чем отличается ceil от ceill и ceilf . В конце статьи вы найдете упражнения для закрепления материала.

Как округлить число вверх в C/C++

Для того, чтобы округлить число вверх в C/C++ мы можем воспользоваться встроенной функцией ceil . Эта функция доступна нам после подключения файла . В C++ можно подключить . Вот как выглядит прототип этой функции:

double ceil (double x);
  • Единственным аргументом функция принимает число, которое нужно округлить.
  • Возвращает функция результат округления.

Давайте посмотрим на пример:

#include #include using namespace std; int main()  cout  <"ceil(3) token operator"> <ceil(3)  ; cout  <"ceil(12.34) token operator"> <ceil(12.34)  ; cout  <"ceil(1.0000001) token operator"> <ceil(1.0000001)  ; cout  <"ceil(0) token operator"> <ceil(0)  ; cout  <"ceil(-0.25) token operator"> <ceil(-0.25)  ; cout  <"ceil(-2) token operator"> <ceil(-2)  ; return 0; >
ceil(3) = 3 ceil(12.34) = 13 ceil(1.0000001) = 2 ceil(0) = 0 ceil(-0.25) = -0 ceil(-2) = -2

Что будет выведено на экран?

#include #include using namespace std; int main()  double a = -12.34; cout  <ceil(a)  ; return 0; >

Функция ceil возвращает наименьшее целое число, которое больше или равно округляемому числу. В данном случае это -12.

Как реализовать ceil самому

Давайте попробуем реализовать функцию ceil сами:

#include using namespace std; double my_ceil(double x)  // Приведем число к целочисленному типу(это обрежет дробную часть) int int_part = (int)x; // Если число уже целое, возвращаем его if (x == int_part)  return int_part; > // Если число отрицательное, возвращаем его как целое число // Так как отрицательное число при округлении вверх идет к ближайшему // большему отрицательному числу (например, ceil(-2.3) = -2), // это эквивалентно простому преобразованию к целому числу else if (x  0)  return int_part; > // Если число положительное и не целое, добавляем 1 к целой части числа else  return int_part + 1; > > int main()  cout  <"my_ceil(3) token operator"> <my_ceil(3)  ; cout  <"my_ceil(12.34) token operator"> <my_ceil(12.34)  ; cout  <"my_ceil(1.0000001) token operator"> <my_ceil(1.0000001)  ; cout  <"my_ceil(0) token operator"> <my_ceil(0)  ; cout  <"my_ceil(-0.25) token operator"> <my_ceil(-0.25)  ; cout  <"my_ceil(-2) token operator"> <my_ceil(-2)  ; return 0; >
my_ceil(3) = 3 my_ceil(12.34) = 13 my_ceil(1.0000001) = 2 my_ceil(0) = 0 my_ceil(-0.25) = 0 my_ceil(-2) = -2

Функции ceill и ceilf

Функции ceill и ceilf , как и ceil , округляют переданное число вверх. Разница только в том, что они работают с вещественными числами long double ( ceill ) и float ( ceilf ). Давайте посмотрим на пример:

#include #include using namespace std; int main()  cout  <"ceill(12.34) token operator"> <ceill(12.34)  ; cout  <"ceil (12.34) token operator"> <ceil(12.34)  ; cout  <"ceilf(12.34) token operator"> <ceilf(12.34)  ; return 0; >
ceill(12.34) = 13 ceil (12.34) = 13 ceilf(12.34) = 13

Как вы можете видеть, они возвращают одно и то же число, просто другого типа.

  1. Применение ceil :
    • Напишите программу на C++, которая запрашивает у пользователя вещественное число.
    • Примените к нему функцию ceil и выводите результат.
    • Ваша программа должна также выводить исходное число пользователя.
  2. Реализация своей версии ceil :
    • Используя предоставленный в статье пример, напишите свою версию функции ceil . Ваша функция должна быть названа my_ceil и принимать число типа double .
    • Проверьте её работу, используя различные числа, и сравните результаты с встроенной функцией ceil .
  3. Сравнение ceil , ceill и ceilf :
    • Напишите программу, которая демонстрирует различия между ceil , ceill , и ceilf .
    • Ваша программа должна включать в себя вызовы всех трёх функций и вывод результатов их работы на экран.

Читайте также

Функция exp используется в языках C и C++ для вычисления экспоненты. В статье будут разобраны примеры использования этой функции. Также в конце статьи есть упражнения.

Функция find в C++
Разберемся в функции find из C++ и научимся использовать ее с такими контейнерами, как vector и set.
fprintf в C/C++

Функция fprintf используется в языках C и C++ для форматирования строки с выводом ее в файл. В статье будут разобраны примеры использования этой функции. Также в конце статьи есть упражнения.

scanf в C/C++

Функция scanf используется в языках C и C++ для считывания значений из стандартного ввода (обычно пользователь использует для этого клавиатуру). В статье будут разобраны примеры использования этой функции, а также мы подробно разберем все спецификаторы формата, которые поддерживает эта функция.

snprintf в C/C++

Функция snprintf используется в языках C и C++ для форматирования строки без вывода ее на экран. В статье будут разобраны примеры использования этой функции. Также в конце статьи есть упражнения.

Функция rand в C++

Язык C++ имеет несколько способов генерации случайных чисел. Функция rand — один из самых популярных способов получить случайное число. В этой статье мы научимся использовать эту функцию, генерировать случайные числа в диапазоне, а также реализуем свой простенький генератор случайных чисел.

В данном уроке пойдет речь о функции pow в C++. Мы рассмотрим с примерами, как возвести число в степень, а также какие есть альтернативы у данной функции.

Функция fabs в C++

В данной статье мы разберемся как работает функция fabs в C++. Также мы узнаем в чем отличие fabs от abs и реализуем свою версию данной функции.

fscanf в C/C++

Функция fscanf используется в языках C и C++ для считывания значений из файла. В статье будут разобраны примеры использования этой функции. Также в конце статьи есть упражнения.

string::size в C++

C++ предлагает разнообразные инструменты для работы со строками, и одна из самых важных функций — это string::size. В этой статье мы подробно рассмотрим эту функцию, поймем, как она измеряет строки, и исследуем ее практическое применение.

vector::size в C++

В C++, контейнер std::vector представляет собой динамический массив, который может автоматически изменять свой размер. Часто возникает необходимость определить, сколько элементов на данный момент содержит vector. Встречайте функцию size! В этой статье мы рассмотрим, как работает функция size, покажем практические примеры и расскажем о других полезных функциях.

strlen в C/C++

Функция strlen используется в языке программирования C для подсчета количества символов в строке. В статье будут разобраны примеры использования этой функции. Также мы реализуем эту функцию сами, а в конце статьи есть упражнения для закрепления материала.

sprintf в C/C++

Функция sprintf — это близкий аналог функции printf. Основное отличие между ними заключается в том, что sprintf не выводит отформатированную строку на экран, а записывает ее по указанному адресу. Эта функция часто используется в C/C++ и рекомендуется к изучению.

Функция itoa в C++

Функция itoa позволяет сконвертировать число в строку. itoa не является частью стандарта C++, поэтому мы разберем как использовать данную функцию когда она есть в вашем компиляторе, а потом реализуем данную функцию сами.

Функция srand используется в языке программирования C++ для инициализации генератора случайных чисел. В статье будут разобраны примеры использования этой функции. В конце статьи есть упражнения для закрепления материала.

Функция tan в C++

C++ предоставляет множество методов для работы с углами. Одна из таких функций – это tan, которая позволяет нам вычислить тангенс угла. В этой статье вы узнаете, как использовать эту функцию, увидите её в действии и даже создадите свою простую программу с использованием tan.

map::count в C++

C++ предлагает множество функций для работы с контейнерами. Одна из таких функций, count, позволяет узнать, существует ли ключ в std::map. В этой статье вы узнаете, когда она может вам пригодится.

Векторы в C++

В этом уроке вы узнаете, что такое вектор в C++, а также если вы хотите узнать, как правильно пользоваться и какие функции к им применять — то вам сюда.

strcat в C/C++

Функция strcat используется в языках C и C++ для соединения (конкатенации) строк. В статье будут разобраны примеры использования этой функции. Также в конце статьи есть упражнения.

vector::push_back в C++

Язык C++ предоставляет различные способы работы с данными. Функция push_back — это популярный метод добавления элементов в вектор. В этой статье мы подробно рассмотрим эту функцию, разберемся, как и когда её использовать, и обсудим некоторые интересные моменты, связанные с ней.

Функция puts используется в языке программирования C для вывода строки на экран используя стандартный вывод. В статье будут разобраны примеры использования этой функции. Также мы реализуем эту функцию сами, а в конце статьи есть упражнения для закрепления материала.

Функция atoi в C++

Функция atoi позволяет получить число из строки. В данной статье вы узнаете, как использовать данную функцию, возможные проблемы, а также реализуете аналог данной функции сами. Закрепить изученный материал нам помогут упражнения в конце статьи.

Стек (stack) в C++

В этой статье вы познакомитесь с структурой данных стек. Мы разберем что это за зверь и как им пользоваться в своей программе. Также мы изучим стек через массив.

Функция map::find в C++

Ключевой функцией std::map в C++ является map::find, которая необходима для быстрого поиска элементов. В этой статье мы рассмотрим назначение этой функции, изучим ее механику и приведем практический пример.»

string::substr в C++

C++ предлагает различные методы работы со строками. Одной из таких функций является substr, которая позволяет извлекать определенные части строки. В этой статье мы рассмотрим функцию substr, узнаем, как она работает, и посмотрим на ее многочисленные применения.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *