Как вывести флоат в си
Ввод-вывод в Си
Основной задачей программирования является обработка информации, поэтому любой язык программирования имеет средства для ввода и вывода информации. В языке Си нет операторов ввода-вывода.
Вывод информации
Функция printf() предназначена для форматированного вывода. Она переводит данные в символьное представление и выводит полученные изображения символов на экран. При этом у программиста имеется возможность форматировать данные, то есть влиять на их представление
на экране.
Общая форма записи функции printf() :
СтрокаФорматов состоит из следующих элементов:
Объекты могут отсутствовать.
Управляющие символы не выводятся на экран, а управляют расположением выводимых символов. Отличительной чертой управляющего символа является наличие обратного слэша ‘\’ перед ним.
Основные управляющие символы:
Форматы нужны для того, чтобы указывать вид, в котором информация будет выведена на экран. Отличительной чертой формата является наличие символа процент ‘%’ перед ним:
Результат работы программы
Тот же самый код может быть представлен с использованием одного вызова printf :
Табличный вывод
При указании формата можно явным образом указать общее количество знакомест и количество знакомест, занимаемых дробной частью:
В приведенном примере 10 — общее количество знакомест, отводимое под значение переменной; 5 — количество позиций после разделителя целой и дробной части (после десятичной точки). В указанном примере количество знакомест в выводимом числе меньше 10, поэтому свободные знакоместа слева от числа заполняются пробелами. Такой способ форматирования часто используется для построения таблиц.
Ввод информации
Функция форматированного ввода данных с клавиатуры scanf() выполняет чтение данных, вводимых с клавиатуры, преобразует их во внутренний формат и передает вызывающей функции. При этом программист задает правила интерпретации входных данных с помощью спецификаций форматной строки.
Общая форма записи функции scanf( ) :
Строка форматов и список аргументов для функции обязательны.
Результат работы программы:
Функция scanf( ) является функцией незащищенного ввода, т.к. появилась она в ранних версиях языка Си. Поэтому чтобы разрешить работу данной функции в современных компиляторах необходимо в начало программы добавить строчку
Комментариев к записи: 96
#include
#include
#include
#include
int main() <
int a[4][5];
int i,j,range,max,maxi,maxj;
float kproiz1,kproiz2;
int proiz1=1;
int proiz2=1;
4.8 – Числовые типы с плавающей точкой
Типы данных с плавающей запятой всегда идут со знаком (могут содержать положительные и отрицательные значения).
Категория | Тип | Минимальный размер | Типовой размер |
---|---|---|---|
С плавающей запятой | float | 4 байта | 4 байта |
double | 8 байт | 8 байт | |
long double | 8 байт | 8, 12 или 16 байт |
Ниже показан пример определения чисел с плавающей запятой:
При использовании литералов с плавающей точкой всегда включайте хотя бы один знак после десятичной точки (даже если этот знак равен 0). Это помогает компилятору понять, что число принадлежит типу плавающей точкой, а не к целочисленному типу.
Лучшая практика
Всегда проверяйте, соответствует ли тип ваших литералов типу переменных, которым они назначаются или используются для инициализации. В противном случае произойдет ненужное преобразование, возможно, с потерей точности.
Предупреждение
Убедитесь, что вы не используете целочисленные литералы там, где должны использоваться литералы с плавающей точкой. Это включает в себя инициализацию или присвоение значений объектам с плавающей точкой, выполнение арифметических операций с плавающей точкой и вызов функций, ожидающих значений с плавающей точкой.
Печать чисел с плавающей точкой
Теперь рассмотрим следующую простую программу:
Результаты работы этой, казалось бы, простой программы могут вас удивить:
В первом случае std::cout напечатал 5, хотя мы ввели 5.0. По умолчанию std::cout не будет печатать дробную часть числа, если она равна 0.
Во втором случае число печатается так, как мы и ожидали.
В третьем случае напечаталось число в экспоненциальном представлении (если вам нужно освежить в памяти экспоненциальное представление, смотрите урок «4.7 – Введение в экспоненциальную запись»).
Диапазоны значений типов с плавающей точкой
Предполагая, что используется представление IEEE 754:
80-битный тип с плавающей запятой – это своего рода историческая аномалия. На современных процессорах он обычно реализуется с использованием 12 или 16 байтов (что является более естественным размером для обработки процессорами).
Может показаться немного странным, что 80-битный тип с плавающей запятой имеет тот же диапазон значений, что и 16-байтовый тип с плавающей запятой. Это связано с тем, что у них одинаковое количество бит, выделенных для показателя степени, однако 16-байтовое число может хранить больше значащих цифр.
Точность с типов плавающей запятой
Рассмотрим дробь 1/3. Десятичное представление этого числа – 0,33333333333333… с тройками, уходящими в бесконечность. Если бы вы писали это число на листе бумаги, ваша рука в какой-то момент устала бы, и вы, в конце концов, прекратили бы писать. И число, которое у вас осталось, будет близко к 0,3333333333…. (где 3-ки уходят в бесконечность), но не совсем.
На компьютере число бесконечной длины потребует для хранения бесконечной памяти, но обычно у нас есть только 4 или 8 байтов. Эта ограниченная память означает, что числа с плавающей запятой могут хранить только определенное количество значащих цифр – и что любые дополнительные значащие цифры теряются. Фактически сохраненное число будет близко к необходимому, но не точно.
Точность числа с плавающей запятой определяет, сколько значащих цифр оно может представлять без потери информации.
При выводе чисел с плавающей точкой std::cout по умолчанию имеет точность 6, то есть предполагает, что все переменные с плавающей точкой имеют только до 6 значащих цифр (минимальная точность с плавающей точкой), и, следовательно, он будет отсекать всё, что идет дальше.
Следующая программа показывает усечение std::cout до 6 цифр:
Эта программа выводит:
Обратите внимание, что каждое из напечатанных значений имеет только 6 значащих цифр.
Число цифр точности переменной с плавающей запятой зависит как от размера (у float точность меньше, чем у double ), так и от конкретного сохраняемого значения (некоторые значения имеют большую точность, чем другие). Значения float имеют точность от 6 до 9 цифр, при этом большинство значений float имеют не менее 7 значащих цифр. Значения double имеют от 15 до 18 цифр точности, при этом большинство значений double имеют не менее 16 значащих цифр. Значения long double имеет минимальную точность 15, 18 или 33 значащих цифр в зависимости от того, сколько байтов этот тип занимает.
Проблемы с точностью влияют не только на дробные числа, они влияют на любое число со слишком большим количеством значащих цифр. Рассмотрим большое число:
Следовательно, нужно быть осторожным при использовании чисел с плавающей запятой, которые требуют большей точности, чем могут содержать переменные.
Лучшая практика
Ошибки округления затрудняют сравнение чисел с плавающей запятой
С числами с плавающей запятой сложно работать из-за неочевидных различий между двоичными (как хранятся данные) и десятичными (как мы думаем) числами. Рассмотрим дробь 1/10. В десятичном формате ее легко представить как 0,1, и мы привыкли думать о 0,1 как о легко представимом числе с 1 значащей цифрой. Однако в двоичном формате 0,1 представлен бесконечной последовательностью: 0,00011001100110011… Из-за этого, когда мы присваиваем 0,1 числу с плавающей точкой, мы сталкиваемся с проблемами точности.
Эффект от этого можно увидеть в следующей программе:
Эта программ выводит следующее:
Ошибки округления также могут иметь неожиданные последствия:
Хотя можно было ожидать, что d1 и d2 должны быть равны, мы видим, что это не так. Если бы мы сравнивали d1 и d2 в программе, программа, вероятно, не работала бы так, как ожидалось. Поскольку числа с плавающей запятой имеют тенденцию быть неточными, их сравнение обычно проблематично – мы обсудим эту тему (и решения) подробнее в уроке «5.6 – Операторы отношения и сравнение значений с плавающей запятой».
Последнее замечание об ошибках округления: математические операции (такие как сложение и умножение), как правило, приводят к увеличению ошибок округления. Таким образом, даже несмотря на то, что 0,1 имеет ошибку округления в 17-й значащей цифре, когда мы складываем 0,1 десять раз, ошибка округления добралась бы и до 16-й значащей цифры. Продолжение операций приведет к тому, что эта ошибка станет всё более значительной.
Ключевые выводы
Следствие этого правила: будьте осторожны с использованием чисел с плавающей запятой для финансовых или валютных данных.
NaN и Inf
Ниже приведена программа, показывающая все эти три категории чисел с плавающей точкой:
И результаты работы этой программы при использовании Visual Studio 2008 в Windows:
INF означает бесконечность, а IND означает неопределенность. Обратите внимание, что результаты печати Inf и NaN зависят от платформы, поэтому ваши результаты могут отличаться.
Лучшая практика
Вообще избегайте деления на 0, даже если ваш компилятор поддерживает это.
Заключение
Подводя итог, вы должны помнить две вещи о числах с плавающей запятой:
Типы данных и их вывод
В этом уроке мы познакомимся с особенностями функции printf() и типами данных: целыми и вещественными числами, символами, массивами и строками. Это далеко не все допустимые в C типы. Есть еще указатели, структуры, объединения, перечисления, также в C есть возможность определять собственные типы данных.
Функция printf() и форматированный вывод
Вывод символов на экран, а точнее в стандартный поток вывода, осуществляется в языке C помощью функции printf(). Эта функция выводит на экран строку, переданную первым аргументом, предварительно заменив в ней специальные комбинации символов преобразованными в символы данными, переданными последующими аргументами. Следующие после первой строки данные могут быть строками, символами, целыми или вещественными числами, а также указателями. У каждого типа данных имеется свое обозначение — своя спецификация формата.
На прошлом уроке мы выводили строку «Hello World» вот так:
Однако то же самое можно было получить так:
Здесь %s — это спецификация строкового формата, т. е. вместо %s будет подставлен следующий аргумент, данные которого должны быть строкой. Вывод целого числа может выглядеть так:
Вместо числа 5 может стоять переменная целочисленного типа. Функция printf() может принимать произвольное число аргументов:
При выводе данные подставляются по очередности следования: 3 на место первой спецификации, dogs на место второй и т.д. То есть следует строго соблюдать соответствие форматов и последующих данных.
Под выводимые данные можно выделять больше знакомест, чем необходимо. Для этого между знаком % и буквой формата прописывается целое число, обозначающие ширину поля, например так: %10d. По умолчанию выравнивание происходит по правому краю. Для выравнивания по левому краю перед числом ставится знак минус.
Напишите программу, которая выводила бы на экране данные примерно так, как на картинке. При этом используйте возможность задать ширину поля, а также выравнивание по левому и правому краям.
Целочисленные типы
В языке C существует несколько типов целых чисел. Они различаются между собой объемом памяти, отводимым под переменную, а также возможностью присваивания положительных и отрицательных значений. От объема памяти, т. е. от количества выделяемых байтов под переменную, зависит, каким может быть максимально возможное значение, записанное в данную переменную. Следует отметить, что в языке Си объем памяти, выделяемый под конкретный тип, может зависеть от операционной системы.
Часто в программах используется тип int. Вот пример, где происходит объявление и определение (присваивание значений) целочисленных переменных, а также вывод их значений на экран:
Обратите внимание, что в языке C присваивать значение можно при объявлении переменных.
Результат будет таким:
Чтобы понять, почему такое происходит, представьте себе числовую ось не в виде прямой, а в виде окружности. Когда мы достигаем конца, двигаясь например по часовой стрелке, то это значит, что мы пришли в начало. Поэтому, продолжая движение по часовой стрелке, следующее число, которое мы увидим за максимально возможным, – это самое минимальное. Данную особенность языка Си следует иметь в виду при выполнении арифметических действий.
То же самое с минимумом int. Если мы начнем из него вычитать, т. е. двигаться против часовой стрелки, то перескочим максимальную границу и будем идти в направлении уменьшения уже от нее:
Помимо типа int в языке программирования C существуют другие (модифицированные) целочисленные типы:
short — отводится меньше байтов, чем на int;
long — отводится больше байтов, чем на int (не всегда, зависит от системы);
unsigned — столько же байт как у int, но без отрицательных чисел; в результате чего знаковый разряд освобождается, и количество положительных значений увеличивается;
При выводе длинных чисел следует дополнять спецификацию формата буквой l перед буквой формата. Например:
Символы
Под символьный тип данных отводится 1 байт памяти. У каждого символа есть соответствующее ему целое число по таблице символов ASCII.
С другой стороны, если переменная задана как int или short и ей присвоено значение в диапазоне, где оно может быть представлено символом, то значение можно вывести как символ. Соответственно целочисленной переменной можно присвоить символ.
Если в программе вы будете использовать целые числа со значениями до 127 или 255 и хотите сэкономить память, то объявите переменную как char или unsigned char.
Получается, что в программе символы — это числа, а числа — символы. Тогда как указать, что мы хотим видеть на экране: символ или число? Для вывода на экран символов используется спецификация формата вида %c.
Так программа, представленная ниже,
выдает такой результат:
Число 63 по таблице символов ASCII соответствует знаку ‘?’. Сначала мы выводим значение переменной ch в формате символа, затем – числа. Тоже самое с переменной uch, однако ее значение было задано через символ, а не число.
Вещественные типы данных
В языке C существует три типа чисел с плавающей точкой: float и double (двойной точности) и long double. Также существует три формата вывода вещественных чисел, причем они не связаны с типами, а связаны с удобством представления числа. Вещественные числа могут иметь высокую точность, очень маленькое или очень большое значение. Если выполнить функции printf() с такими параметрами:
, то на экране мы увидим следующее:
В первом случае (%f) выводится число в обычном виде. По умолчанию точность представления числа равна шести знакам после точки.
Четвертый формат (%e) выведет число исключительно в нормализованном виде, каким бы это вещественное число ни было.
Если при выводе требуется округлить число до определенной точности, то перед буквой-форматом ставят точку и число-указатель точности. Например, printf(«%.2f», 0.23) выведет на экран 0.23, а не 0.230000. Когда требуется указать еще и поле, то его ширину прописывают перед точкой, например, %10.3f.
Массивы
Переменные, содержащие массивы, в языке программирования C объявляются, например, так:
Если при указании количества элементов используется константа, она должна быть определена до своего использования следующим образом (чаще константы определяют вне функций):
На самом деле #define является командой препроцессора, используемой не только для определения констант. Когда препроцессор обрабатывает исходный файл программы, он подставляет во все места, где была упомянута константа, ее значение.
Индексация массивов в языке программирования C начинается с нуля.
Присваивание значений элементам массивов можно произвести сразу или в процессе выполнения программы. Например:
Когда переменная-массив объявляется и сразу определяется (как в случае vowels), то размер массива можно не указывать, т. к. он вычисляется по количеству элементов, переданных в фигурных скобках.
Строки
В языке программирования С нет отдельного строкового типа данных, хотя формат вывода строки есть (%s). Строки в C – это массивы символов, последний элемент которых является первым (с номером 0) символом в таблице ASCII. В этом месте таблицы стоит «ничто», имеющее символьное обозначение ‘\0’.
С другой стороны, строки — это необычные массивы в том смысле, что работа с ними в языке программирования C несколько отличается от работы с числовыми массивами. В этом мы убедимся позже.
Выше мы объявили и определили массив vowels. Если бы мы его определили вот так:
то он был бы строкой. Во втором случае сами двойные кавычки «говорят» что это строка, и символ окончания строки ‘\0’ записывается в память автоматом.
Массивы символов можно выводить на экран, просто указав имя переменной, а вот с массивами чисел такой номер не пройдет:
Функция sizeof()
Функция sizeof() языка C принимает в качестве аргумента константу, тип данных или переменную и возвращает количество байт, которые отведено под этот объект в памяти.
При выводе на экран значения, возвращаемого sizeof() используется формат %lu (длинное целое без знака). Примеры:
Напишите программу, выводящую информацию о количестве байтов, отводимых в памяти под типы данных, которые были изучены на данном уроке. При работе с массивами символов, определяемыми как строковые литералы (в двойных кавычках), обратите внимание, что размер массива больше на единицу, чем количество видимых символов.
Форматированный ввод и вывод
Форматированный вывод
Сегодня мы рассмотрим две важные функции форматированного ввода и вывода. Устройство и работу этих функций полностью можно понять только после изучения работы с указателями и функций с переменным числом параметров. Но пользоваться этими функциями необходимо уже сейчас, так что некоторые моменты придётся пропустить.
Функция проходит по строке и заменяет первое вхождение % на первый аргумент, второе вхождение % на второй аргумент и т.д. Далее мы будем просто рассматривать список флагов и примеры использования.
Общий синтаксис спецификатора формата
%[флаги][ширина][.точность][длина]спецификатор
Спецификатор – это самый важный компонент. Он определяет тип переменной и способ её вывода.
Спецификатор | Что хотим вывести | Пример |
---|---|---|
d или i | Целое со знаком в в десятичном виде | 392 |
u | Целое без знака в десятичном виде | 7235 |
o | Беззнаковое в восьмеричном виде | 657 |
x | Беззнаковое целое в шестнадцатеричном виде | 7fa |
X | Беззнаковое целое в шестнадцатеричном виде, верхний регистр | 7FA |
f или F | Число с плавающей точкой | 3.4563745 |
e | Экспоненциальная форма для числа с плавающей точкой | 3.1234e+3 |
E | Экспоненциальная форма для числа с плавающей точкой, верхний регистр | 3.1234E+3 |
g | Кратчайшее из представлений форматов f и e | 3.12 |
G | Кратчайшее из представлений форматов F и E | 3.12 |
a | Шестнадцатеричное представление числа с плавающей точкой | -0xc.90fep-2 |
A | Шестнадцатеричное представление числа с плавающей точкой, верхний регистр | -0xc.90FEP-2 |
c | Буква | a |
s | Строка (нуль-терминированный массив букв) | Hello World |
p | Адрес указателя | b8000000 |
n | Ничего не печатает. Аргументом должен быть указатель на signed int. По этому адресу будет сохранено количество букв, которое было выведено до встречи %n | |
% | Два идущих друг за другом процента выводят знак процента | % |
Суб-спецификатор длины изменяет длину типа. В случае, если длина не совпадает с типом, по возможности происходит преобразование до нужного типа.
спецификаторы | |||||||
---|---|---|---|---|---|---|---|
Длина | d, i | u o x X | f F e E g G a A | c | s | p | n |
(none) | int | unsigned int | double | int | char* | void* | int* |
hh | signed char | unsigned char | signed char* | ||||
h | short int | unsigned short int | short int* | ||||
l | long int | unsigned long int | wint_t | wchar_t* | long int* | ||
ll | long long int | unsigned long long int | long long int* | ||||
j | intmax_t | uintmax_t | intmax_t* | ||||
z | size_t | size_t | size_t* | ||||
t | ptrdiff_t | ptrdiff_t | ptrdiff_t* | ||||
L | long double |
Форматированный ввод
Как и в printf, ширина, заданная символом * ожидает аргумента, который будт задавать ширину. Флаг длина совпадает с таким флагом функции printf.
Кроме функций scanf и printf есть ещё ряд функций, которые позволяют получать вводимые данные
Это не полный набор различных функций символьного ввода и вывода. Таких функций море, но очень многие из них небезопасны, поэтому перед использованием внимательно читайте документацию.
Непечатные символы
В си определён ряд символов, которые не выводятся на печать, но позволяют производить форматирование вывода. Эти символы можно задавать в виде численных значений, либо в виде эскейп-последовательностей: символа, экранированного обратным слешем.
Урок №33. Типы данных с плавающей точкой: float, double и long double
Обновл. 11 Сен 2021 |
Типы данных с плавающей точкой
Есть три типа данных с плавающей точкой: float, double и long double. Язык C++ определяет только их минимальный размер (как и с целочисленными типами). Типы данных с плавающей точкой всегда являются signed (т.е. могут хранить как положительные, так и отрицательные числа).
Тип | Минимальный размер | Типичный размер | |
Тип данных с плавающей точкой | float | 4 байта | 4 байта |
double | 8 байт | 8 байт | |
long double | 8 байт | 8, 12 или 16 байт |
Объявление переменных разных типов данных с плавающей точкой:
Если нужно использовать целое число с переменной типа с плавающей точкой, то тогда после этого числа нужно поставить разделительную точку и нуль. Это позволяет различать переменные целочисленных типов от переменных типов с плавающей запятой:
Обратите внимание, литералы типа с плавающей точкой по умолчанию относятся к типу double. f в конце числа означает тип float.
Экспоненциальная запись
Обычно, в экспоненциальной записи, в целой части находится только одна цифра, все остальные пишутся после разделительной точки (в дробной части).
На практике экспоненциальная запись может использоваться в операциях присваивания следующим образом: