Установка десятичной точности в языке C

Эта статья покажет вам, как установить десятичную точность в языке программирования C. Сначала мы определим точность, а затем рассмотрим несколько примеров, чтобы показать, как установить десятичную точность в программировании на C.
Десятичная точность в C
Переменная целочисленного типа обычно используется для хранения целого числа, а переменная типа с плавающей запятой — для хранения действительных чисел с дробными частями, например 2.449561 или -1.0587. Точность определяет точность действительных чисел и обозначается точкой (.) символ. Точность или точность действительных чисел указывается количеством цифр после десятичной точки. Итак, точность означает количество цифр, указанных после десятичной точки в числе с плавающей запятой. Например, цифра 2.449561 имеет точность шесть и -1.058 имеет точность три.

В соответствии с представлением с плавающей запятой одинарной точности IEEE-754, всего 32 бита для хранения действительного числа. Из 32 битов наиболее значимый бит используется как знаковый бит, следующие 8 бит используются как показатель степени, а следующие 23 бита используются как дробь. 
В случае представления IEEE-754 с плавающей запятой двойной точности существует всего 64 бита для хранения действительного числа. Из 64 бит наиболее значимый бит используется как знаковый бит, следующие 11 бит используются как показатель степени, а следующие 52 бита используются как дробь.
Однако при печати действительных чисел необходимо указывать точность (другими словами, точность) действительного числа. Если точность не указана, будет учитываться точность по умолчанию, i.е., шесть десятичных цифр после десятичной точки. В следующих примерах мы покажем вам, как указать точность при печати чисел с плавающей запятой на языке программирования C.
Примеры
Теперь, когда у вас есть базовое представление о точности, давайте рассмотрим пару примеров:
-
- Точность по умолчанию для числа с плавающей запятой
- Точность по умолчанию для double
- Установить точность для поплавка
- Установить точность для двойного
Пример 1: точность по умолчанию для поплавка
В этом примере показано, что точность по умолчанию установлена на шесть цифр после десятичной точки. Мы инициализировали переменную типа float значением 2.7 и распечатал его без явного указания точности.
В этом случае настройка точности по умолчанию гарантирует, что будут напечатаны шесть цифр после десятичной точки.
#включать
int main ()поплавок f = 2.7;
printf («\ nЗначение f =% f \ n», f);
printf («Размер float =% ld \ n», sizeof (float));
возврат 0;
Пример 2: точность по умолчанию для Double
В этом примере вы увидите, что точность по умолчанию установлена на шесть цифр после десятичной точки для переменных типа double. Мы инициализировали переменную типа double, i.е., d, со значением 2.7 и распечатал без указания точности. В этом случае настройка точности по умолчанию гарантирует, что будут напечатаны шесть цифр после десятичной точки.
#включать
int main ()двойной d = 2.7;
printf («\ nЗначение d =% lf \ n», d);
printf («Размер double =% ld \ n», sizeof (double));
возврат 0;
Пример 3: установка точности для поплавка
Теперь мы покажем вам, как установить точность для значений с плавающей запятой. Мы инициализировали переменную типа float, i.е., f со значением 2.7, и распечатал его с различными настройками точности. Когда мы упоминаем «% 0.4f »в операторе printf, это означает, что мы заинтересованы в выводе четырех цифр после десятичной точки.
#включать
int main ()поплавок f = 2.7;
/ * устанавливаем точность для переменной с плавающей запятой * /
printf («\ nЗначение f (точность = 0.1) =% 0.1f \ n «, f);
printf («\ nЗначение f (точность = 0.2) =% 0.2f \ n «, f);
printf («\ nЗначение f (точность = 0.3) =% 0.3f \ n «, е);
printf («\ nЗначение f (точность = 0.4) =% 0.4f \ n «, f);
printf («\ nЗначение f (точность = 0.22) =% 0.22f \ n «, f);
printf («\ nЗначение f (точность = 0.23) =% 0.23f \ n «, f);
printf («\ nЗначение f (точность = 0.24) =% 0.24f \ n «, f);
printf («\ nЗначение f (точность = 0.25) =% 0.25f \ n «, f);
printf («\ nЗначение f (точность = 0.40) =% 0.40f \ n «, f);
printf («Размер float =% ld \ n», sizeof (float));
возврат 0;
Пример 4: установка точности для двойного
В этом примере мы увидим, как установить точность для значений типа double. Мы инициализировали переменную типа double, i.е., d, со значением 2.7 и распечатал его с различными настройками точности. Когда мы упоминаем «% 0.52f »в операторе printf, это означает, что мы заинтересованы в выводе 52 цифр после десятичной точки.
#включать
int main ()поплавок f = 2.7;
/ * устанавливаем точность для переменной с плавающей запятой * /
printf («\ nЗначение f (точность = 0.1) =% 0.1f \ n «, f);
printf («\ nЗначение f (точность = 0.2) =% 0.2f \ n «, f);
printf («\ nЗначение f (точность = 0.3) =% 0.3f \ n «, е);
printf («\ nЗначение f (точность = 0.4) =% 0.4f \ n «, f);
printf («\ nЗначение f (точность = 0.22) =% 0.22f \ n «, f);
printf («\ nЗначение f (точность = 0.23) =% 0.23f \ n «, f);
printf («\ nЗначение f (точность = 0.24) =% 0.24f \ n «, f);
printf («\ nЗначение f (точность = 0.25) =% 0.25f \ n «, f);
printf («\ nЗначение f (точность = 0.40) =% 0.40f \ n «, f);
printf («Размер float =% ld \ n», sizeof (float));
возврат 0;
Заключение
Точность — очень важный фактор для представления действительного числа с достаточной точностью. Язык программирования c предоставляет механизм для контроля точности или точности действительного числа. Однако мы не можем изменить фактическую точность действительного числа. Например, дробная часть 32-битного числа с плавающей запятой одинарной точности представлена 23 битами, и это фиксировано; мы не можем изменить это для конкретной системы. Мы можем только решить, какую точность мы хотим, установив желаемую точность действительного числа. Если нам нужна большая точность, мы всегда можем использовать 64-битное число с плавающей запятой двойной точности.
Вывод double с нужной точностью и в нужном формате
Требуется вывести double с максимальной точностью, при этом целую часть, которая не превышает 999 вывести с пробелами на месте отсутствующих цифр, типа 9,12.
Вывожу следующим образом
Возникло 2 проблемы:
1) везде читал, что точность double определяется как std::numeric_limits<double>::digits10 , однако похоже, что можно вытащить больше значащих цифр, если задать точность в 20 цифр, то будут видны все 20 отличных от 0 цифр
2) не нашел, как можно задать размер целой части, чтобы заполнить отсутствующие цифры пробелами
Подскажите, что требуется сделать?


Всё, чего вам не хватало, это задать заполнитель setfill и ширину setw выводимого поля:

Можно также написать класс, с функциональностью выводить как угодно. Например:
И пример программы:
Можно и манипулятор написать, но такой класс, думаю, более полезен в том смысле, что может выдавать целую и дробную части

Во-первых, смысл величины digits10 для плавающего типа T заключается в том, что если вы возьмете десятичное строковое представление, преобразуете его в значение типа T , а затем преобразуете его из T обратно в десятичное строковое представление, то вы получите digits10 значащих цифр цифр, совпадающих с вашей исходной строкой. Например, если вы используете плавающий тип для хранения целых значений, то целые значения с таким количеством цифр будут представляться без потерь, как и соседние (+-1) целые значения.
Родственной величиной является величина max_digits10 , которая говорит, что если вы преобразуете плавающее значение типа T в десятичное строковое представление с сохранением max_digits10 старших значащих цифр, а затем преобразуете его обратно в тип T , то вы гарантированно получите исходное значение типа T .
Таким образом, величина digits10 описывает сохранение данных в преобразовании туда-обратно вида «строка10 -> плавающее -> строка10«. А величина max_digits10 описывает сохранение данных в преобразовании туда-обратно вида «плавающее -> строка10 -> плавающее».
Это, однако, совсем не означает, что десятичное строковое плавающее значение будет иметь только столько точных цифр. Огульно обзывать цифры за пределами этого количества «мусором» — очевидная профанация. Какие цифры являются точными, а какие нет — определяется спецификой ваших вычислений и известно только вам.
Очевидный пример: «традиционные» двоичные плавающие типы способны точно представлять степени двойки в пределах возможностей экспоненты. То есть std::pow(2, 512) даст вам точное значение типа double
в котором намного больше значащих цифр, чем digits10 или max_digits10 для double ( 15 и 17 соответственно). Никакого «мусора» в этом представлении нет (разумеется, если вы хотели вычислить именно 2 512 ) . Вас это не должно удивлять. Умение пользоваться такими возможностями плавающих представлений — это во многом и есть умение пользоваться плавающими типами в общем.
Во-вторых, что касается управления шириной поля при выводе — об этом вы уже получили ответы.
По ходу обсуждения оказалось, что имеет смысл остановиться подробнее на определении точности вещественного типа. Удивительно, но оказывается, что точность double совсем не жалкие 15 цифр, а намного, намного больше! И в подтверждение приводятся числа 2^(-100) и 2^512, которые действительно представляются точно. Так что же, получается что и в самом деле точность double больше, чем 15 цифр? К сожалению нет, такие заявления говорят лишь о непонимании вещественной арифметики.
Давайте посмотрим на представление чисел вещественным типом. Точность представления определяется его мантиссой, которая в случае числа двойной точности имеет длину 52 бита и соответственно может представить 2^52 значений. Теперь возьмем некое число, у которого в двоичном представлении биты мантиссы 53, 54, и т.д. являются нулями. Нетрудно видеть, что такое число будет представлено абсолютно точно. С бесконечной точностью! И таких чисел существует ровно 2^52.
Попробуем теперь немного уменьшить требования к точности. Возьмем, скажем, тысячу знаков после запятой — есть ли числа, которые представляются с такой точностью? Да, такие числа в самом деле есть, и из свойств множества действительных чисел видно, что их бесконечно много. Какую бы точность мы ни задали — сто, тысячу, миллион знаков после запятой, — оказывается, что существует бесконечно много чисел, представимых именно с такой точностью.
Получается, что точность вещественного типа это какая-то странная характеристика, которая произвольно меняется в зависимости от числа вплоть до бесконечности? Нет, именно в этом месте и происходит путаница! Точность представления отдельно взятого числа не имеет никакого отношения к точности вещественного типа. Слово одно, но под ним подразумеваются совершенно разные вещи. А собственно точность представления числа, хотя и кажется очень важной с бытовой точки зрения, в вещественной арифметике никакого значения не имеет. По той простой причине, что она непредсказуема — мы не можем определить точность представления по результату вычислений. Для этого надо этот результат сравнить с эталонным значением, а если мы и так его знаем, то зачем нам что-то вычислять?
Так что же такое точность вещественного типа? Представим, что у нас есть два числа, у которых первые 52 бита мантиссы совпадают, а различается бит 53. Эти два числа будут представлены одной и той же мантиссой, и соответственно, тем же самым числом двойной точности. Мы говорим, что точность double составляет 52 бита, и это означает простую вещь: double различает только числа, у которых отличаются первые 52 бита. Числа, у которых отличаются только биты 53 и последующие, представляются одной и той же мантиссой. Вот это и есть точность! Соответственно,в десятичном виде точность double составляет 15.45 десятичных цифр. Это означает, что числа, отличающиеся первыми 15 знаками всегда представляются разными значениями double . Числа с отличиями в 16-ом знаке могут представляться разными значениями (в 45% случаев), а могут и не отличаться (соответственно, в 55% случаев). Числа с отличием в 17-ом и более младших знаках имеют одинаковое представление в числе двойной точности.
Разумеется, тема точности вещественной арифметики немного сложнее этого простого определения. Для более серьезного ознакомления можно посоветовать Д. Кнут, том 2 «Получисленные алгоритмы«, глава 4.2.2 «Точность выполнения арифметических действий в системе с плавающей точкой«.
Точность float & double
Почему точность Double такая же как у Float ?
Вначале столкнулся с проблемой float: time=65536.0f; (можно и больше число указать) time+=0.003;.Создать функцию с параметрами GetFunctionValue(double& a, double& b, double& c, double& x).
Есть код что считает нужно сделать пару манипуляций что у не могу реализовать 1) создать функцию.Сообщение от Royal_X
Потому что так и есть.
Сообщение от Royal_X
Сообщение от Folian
Сообщение от Folian
Сообщение от Royal_XСообщение от Royal_X
Что значит "точны 7 знаков после запятой"? В сравнении с чем?
Плавающие типы в компьютере являются двоичными. Разговаривать об их абстрактной точности можно только в терминах количества двоичных знаков.
Сообщение от Folian
Сообщение от Royal_X
Сообщение от Royal_X
Сообщение от VerevkinМеню пользователя @ ram876 Сообщение от ram876
Сказали уже или нет, что точность дробных чисел зависит от их порядка?
Грубо очень грубо говоря, если говорить про десятичные дроби.(забудем, что в процессоре на самом деле дроби двоичные)Пусть у тебя есть 6 десятичных разрядов, и два разряда порядка.
Значит ты их можешь запоминать числа от 0.000001*10^-99 до 0.999999*10^99
причём обрати внимание, ты "как бы" можешь запоминать супер большие числа типа 0.999999*10^99,
но значащими в них будут только первые 6 цифрА вот для дробных чисел от 0.100000 до 1.000000 т.е. с порядком равным нулю сохраняются все 6 знаков после запятой
А вот для дробных чисел от 1.00000 до 10.00000 т.е. с порядком равным 1 сохраняются лишь 5 знаков после запятой, т.к. их представляют как например 0,123456*10
А вот для дробных чисел от 10.0000 до 100.0000 т.е. с порядком равным 2 сохраняются лишь 4 знаков после запятой, т.к. их представляют как 0,123456*100Аналогично и с двоичными типами float и double. Чем крупнее число по модулю, тем меньше знаков после запятой оно сможет сохранить.
Как увеличить точность double c

This forum has migrated to Microsoft Q&A. Visit Microsoft Q&A to post new questions.
Answered by:
Question
double dec = (double)d * 45.00 / 1023.00;
In my application, there is a calcuation gives a double result.
I want to display it on a label. however, the lenght of the double value is too long.
How to set the precision of the double value to 3, such as 3.489 and ignore the other digits.
Is there any choice for the rule as "Smaller than 5, just ignore it; otherwise, add 1 to the last element of the value". I do not know how to explain it in English.
I think this should be a simple problem. However, I searched around and could not find a solution.
Any suggestion for searching such basic information?
Answers
You can use the Math.Round method, which takes a double (or decimal, which I recommend for precise calculations like in banking) and the precision.
So Math.Round(2.7182818, 3) returns 2.718.
However, Math.Round is defined to round 5’s to the nearest even number in the preceding digit, not up, unless you call it like:
Math.Round(2.5, 1, MidpointRounding.AwayFromZero), which returns 3 instead of 2. Note that this variant requires .NET version 2.0.
double dec = (double)d * 45.00 / 1023.00;
label.Text = String.Format("<0:F3>", dec); // Show 3 Decimel Points
I hope this will help! Cheers 😉
The better way to do caclulations is with more Decimels which is the nature of Mathematic but for any reason if you need to round in Float, double or decimel you can use Math.Round; there are also other functions like Math.Ciel() Math.Floor(). The other way is to use them only on your anwers not on the values who are participating in the calculations.
The other thing is always use Decimel datatype for mathematic calculations because float and double will not give you accurate results. You can test it with comparison to the calculator and a simple C# application.
All replies
double dec = (double)d * 45.00 / 1023.00;
label.Text = String.Format("<0:F3>", dec); // Show 3 Decimel Points
I hope this will help! Cheers 😉
So I have to change the double to a string to get the desired precision??
Of course it works in this example. However, how to get the double number after setting the precious of it?
It seems there does not exist double.Format() or such method.
I hope you can show me more way to get the result, no matter in string form or double form, I want to have a overall impression of how to set a number’s precision.