Как задать точность в c
Перейти к содержимому

Как задать точность в c

  • автор:

Числовые типы с плавающей запятой (справочник по C#)

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

Характеристики типов с плавающей запятой

C# поддерживает следующие предварительно определенные типы с плавающей запятой:

Ключевое слово или тип C# Приблизительный диапазон значений Точность Размер Тип .NET
float От ±1,5 x 10 −45 до ±3,4 x 10 38 6–9 цифр 4 байта System.Single
double от ±5,0 × 10 −324 до ±1,7 × 10 308 15–17 цифр 8 байт System.Double
decimal от ±1,0 x 10 -28 до ±7,9228 x 10 28 28-29 знаков 16 байт System.Decimal

В приведенной выше таблице каждый тип ключевого слова C# из крайнего левого столбца является псевдонимом для соответствующего типа .NET. Они взаимозаменяемые. Например, следующие объявления объявляют переменные одного типа:

double a = 12.3; System.Double b = 12.3; 

По умолчанию все типы с плавающей запятой имеют значение 0 . Все типы с плавающей запятой имеют константы MinValue и MaxValue с минимальным и максимальными итоговыми значениями этого типа. Типы float и double также предоставляют константы, обозначающие бесконечные и нечисловые значения. Например, тип double предоставляет следующие константы: Double.NaN, Double.NegativeInfinity и Double.PositiveInfinity.

Тип decimal подходит, если требуемая степень точности определяется числом цифр справа от десятичной запятой. Такие числа обычно используются в финансовых приложениях для денежных сумм (например, 1,00 долл. США), процентных ставок (например, 2,625 %) и т. д. Даже числа, точные только к одной десятичной цифре, обрабатываются более точно decimal типом: 0,1, например, может быть точно представлен decimal экземпляром, а double float экземпляр не представляет 0,1. Из-за этой разницы в числовых типах в арифметических вычислениях могут возникать непредвиденные ошибки округления при использовании double или float для десятичных данных. Вы можете использовать double вместо decimal , если оптимизация производительности важнее, чем обеспечение точности. Но любая разница в производительности останется незамеченной для всех приложений, кроме самых требовательных к вычислениям. Еще одна возможная причина, по которой следует избегать decimal , — это минимальные требования к хранилищу. Например, ML.NET использует float , так как разница между 4 байтами и 16 байтами суммируется для очень больших наборов данных. Дополнительные сведения см. в разделе System.Decimal.

В одном и том же выражении можно сочетать и целочисленные типы, и типы float и double . В этом случае целочисленные типы неявно преобразуются в один из типов с плавающей запятой. При необходимости тип float неявно преобразуется в double . Выражение вычисляется следующим образом.

  • Если в выражении есть тип double , оно оценивается как double или bool в реляционных сравнениях или сравнениях на равенство.
  • Если в выражении нет типа double , оно оценивается как float или bool в реляционных сравнениях или сравнениях на равенство.

Можно также смешивать целочисленные типы и тип decimal в выражении. В этом случае целочисленные типы неявно преобразуются в тип decimal , а выражение вычисляется как decimal или bool в реляционных сравнениях и сравнениях на равенство.

Тип decimal нельзя смешивать с типами float и double в выражении. В этом случае, если требуется выполнить арифметические операции или операции сравнения или равенства, необходимо явно преобразовать операнды из типа или в тип decimal , как показано в следующем примере:

double a = 1.0; decimal b = 2.1m; Console.WriteLine(a + (double)b); Console.WriteLine((decimal)a + b); 

Можно использовать строки стандартных числовых форматов или строки пользовательских числовых форматов для форматирования значения с плавающей запятой.

Вещественные литералы

Тип реального литерала определяется его суффиксом следующим образом:

  • Литерал без суффикса или с суффиксом d или D имеет тип double .
  • Литерал с суффиксом f или F имеет тип float .
  • Литерал с суффиксом m или M имеет тип decimal .

В приведенном ниже коде показан пример каждого из них.

double d = 3D; d = 4d; d = 3.934_001; float f = 3_000.5F; f = 5.4f; decimal myMoney = 3_000.5m; myMoney = 400.75M; 

В предыдущем примере также показано использование _ в качестве разделителя цифр. Цифровой разделитель можно использовать со всеми видами числовых литералов.

Можно также использовать экспоненциальное представление, то есть указать экспоненту вещественного литерала, как показано в следующем примере:

double d = 0.42e2; Console.WriteLine(d); // output 42 float f = 134.45E-2f; Console.WriteLine(f); // output: 1.3445 decimal m = 1.5E6m; Console.WriteLine(m); // output: 1500000 

Преобразования

Существует только одно неявное преобразование между числовыми типами с плавающей запятой: из float в double . Однако можно преобразовать любой тип с плавающей запятой в любой другой тип с плавающей запятой с помощьюявного приведения. Для получения дополнительной информации см. статью Встроенные числовые преобразования.

Спецификация языка C#

Дополнительные сведения см. в следующих разделах статьи Спецификация языка C#:

  • Типы с плавающей запятой
  • Тип decimal
  • Вещественные литералы

См. также

  • справочник по C#
  • Типы значений
  • Целочисленные типы
  • Строки стандартных числовых форматов
  • Числовые значения в .NET
  • System.Numerics.Complex

Совместная работа с нами на GitHub

Источник этого содержимого можно найти на GitHub, где также можно создавать и просматривать проблемы и запросы на вытягивание. Дополнительные сведения см. в нашем руководстве для участников.

Спецификатор точности

Спецификатор точности следует за спецификатором минимума ширины поля (если он есть). Он состоит из точки, за которой следует целое число. Его точное значение зависит от типа данных, к которым он применяется.

При применении спецификатора точности к вещественным данным, используя спецификаторы %f, %е или %Е, он определяет число выводимых цифр дробной части. Например, %10.4f выводит числа, по крайней мере, с длиной строки в десять символов, причем под дробную часть отводится четыре символа. Если не указать точность, то по умолчанию используется шесть символов. Когда спецификатор точности применяется к %g или %G, он определяет число значимых цифр. Применение спецификатора точности к строкам ограничивает длину строки. Например, %5.7s выводит строку, по крайней мере, с пятью, но не более чем с семью символами. Если строка длиннее, чем максимальная указанная ширина, оставшиеся символы отбрасываются.

Когда спецификатор точности применяется к целым типам, он указывает минимальное число цифр, отводимых под каждое число. Для достижения требуемой длины к числу добавляются нули. Следующая программа иллюстрирует применение спецификатора точности:

#include
int main (void)
printf («%. 4f\n\»,123.1234567);
printf(«%3.8d\n», 1000);
printf(«%10.15 s\n», «This is a simple test.»);
return 0;
>

В результате ее работы получаем:

123.1235
00001000
This is a simpl

c++: задать точность числа при выводе через printf

Подскажите, как задать точность вывода float / double числа через printf ? У меня сейчас вывод выглядит следующим образом:

printf("a: %20.16f, b: %20.16f, c: %20.16f", a, b, c); 

и настроен под точность double , но иногда я использую float числа (для ускорения расчётов) и тогда мне нужна float точность без вывода дополнительных чисел Как корректнее реализовать выбор соответствующей точность? Есть варианты 1) определять тип данных и для каждого типа использовать свой вариант вывода

template void myprint()

2) формировать строку в зависимости от точности

const int prec = std::numeric_limits::digits10 + 1; const std::string format = "%" + std::to_string(4 + prec) + "." + std::to_string(prec); . 

оба варианта с недостатками (во втором как-то приходится правильно сформировать строку $x.y , что требует относительно много кода для такой задачи, а в первом варианте слишком много if придется наставить) как можно оптимальнее разрешить эту проблему?

C++: Типы данных с плавающей точкой

Целочисленные типы отлично подходят для подсчета целых чисел, но иногда нам нужно хранить очень большие числа или числа с дробной частью. Переменная типа с плавающей точкой – это переменная, которая может содержать действительное число, например 4320,0, -3,33 или 0,01226. Название плавающая точка указывает на то, что десятичная точка может плавать, то есть она может поддерживать переменное количество цифр до и после себя.

Существует три разных типа данных с плавающей точкой: float , double и long double . Как и в случае с целыми числами, C++ не определяет фактические размеры этих типов, но гарантирует минимальные размеры:

  • float – должен иметь как минимум 32-бита и гарантировать минимум 6 значащих цифр
  • double – 48-бит и быть не меньше float. Гарантирует 15 значащих цифр
  • long double – как минимум 80 битов и 18-значащих цифр

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

Ниже представлены примеры определения переменных с плавающей точкой:

float f_num; double d_num; long double ld_num; 

Вы могли заметить, что в имени переменной используется префикс — это делать не обязательно, но это помогает понять переменная кого типа сейчас используется.

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

double d_num < 5.0 >; float f_num < 5.0f >; 

По умолчанию литералы с плавающей точкой имеют тип double . Суффикс f используется для обозначения литерала типа float .

Вы могли заметить, что в коде выше инициализация производится не через оператор присваивания = , а с помощью нотации < 5.0 >. Это списковая инициализация, она пришла в язык с 11 стандарта и она имеет одно преимущество:

int num; num = 3.14; std::cout 3 

В коде выше мы пытаемся сохранить в целочисленную переменную вещественное число. Такая программа скомпилируется и будет работать, но у числа мы потеряем всю вещественную часть.

Если применить списковую инициализацию, получим ошибку компиляции:

int num < 3.14 >; // ошибка int count; count = < 3.14 >; // ошибка 

Рассмотрим такую программу:

int main() < float f_num = < 10.0 / 3.0 >; double d_num = < 10.0 / 3.0 >; std::cout
3.33333 3.33333

Обратите внимание, что каждое из напечатанных значений имеет только 6 значащих цифр. Это стандартное поведение объекта cout , но мы можем переопределить это поведение и повысить точность:

#include #include // для увеличения точности int main() < std::cout ; double d_num = < 10.0 / 3.0 >; std::cout
3.333333253860474 3.333333333333333

Видно, что число float определено не точно и содержит ошибки, поскольку тип float гарантирует нам только шесть значащих цифр.

Существует две особые категории чисел с плавающей точкой. Первая – Inf , которая представляет бесконечность. Inf может быть положительной или отрицательной. Вторая – NaN , что означает Not a Number — не число. Существует несколько различных типов NaN . NaN и Inf доступны только в том случае, если компилятор для чисел с плавающей точкой использует определенный формат. Если используется другой формат, следующий код приводит к неопределенному поведению.

#include int main() < double zero < 0.0 >; double pos_inf < 5.0 / zero >; // положительная бесконечность std::cout ; // отрицательная бесконечность std::cout ; // не число (математически неверно) std::cout
inf -inf nan

Задание

Напишите программу, которая рассчитывает сколько километров проедет автомобиль на полном баке. Пусть объем бака будет 43 литра, а расход 8.8 л на 10 км. Результат выведите на экран.

Упражнение не проходит проверку — что делать? ��

Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:

  • Обязательно приложите вывод тестов, без него практически невозможно понять что не так, даже если вы покажете свой код. Программисты плохо исполняют код в голове, но по полученной ошибке почти всегда понятно, куда смотреть.

В моей среде код работает, а здесь нет ��

Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.

Мой код отличается от решения учителя ��

Это нормально ��, в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.

В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.

Прочитал урок — ничего не понятно ��

Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.

Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.

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

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