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

Float double чем отличаются

  • автор:

Float double чем отличаются

На 32-разрядной платформе ARM, в среде разработки IAR EWB for ARM применены следующие типы float, double и long double.

float — 32-битное число с плавающей точкой. Диапазон чисел от ±1.18E-38 до ±3.39E+38, 7 десятичных разрядов, 8 бит показателя степени (экспонента) и 23 бита основания степени (мантисса).

double — 64-битное число с плавающей точкой. Диапазон чисел от ±2.23E-308 to ±1.79E+308, 15 десятичных разрядов, 11 бит показателя степени (экспонента) и 52 бита основания степени (мантисса).

long double — абсолютно то же самое, что и double.

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

Информация получена из документа справки «IAR C/C++ Development Guide» EWARM_DevelopmentGuide.ENU.pdf, раздел «FLOATING-POINT TYPES».

[См. также]

1. Описание стандартных функций < cmath >(math.h) site:cplusplus.com .
2. Как избавиться от чисел с плавающей точкой.

В чем отличие float/double и decimal?

Здравствуйте, хотел попросить какие-то материалы, которые будут понятны новичку, насчёт ошибок округления и типа decimal, заранее спасибо!

  • Вопрос задан 28 дек. 2022
  • 1318 просмотров

1 комментарий

Простой 1 комментарий

В MSDN смотрели?
https://learn.microsoft.com/ru-ru/dotnet/csharp/la.
Решения вопроса 1

vabka

Василий Банников @vabka Куратор тега C#
Токсичный шарпист

float и double — это числа с плавающей точкой по стандарту IEEE754. Операции с ними происходят достаточно быстро, тк они реализованы в процессоре на аппаратном уровне.
Но они достаточно не точные в плане выражения десятичных дробей. (То самое 0.1+0.2 != 0.3).
Настоящие деньги на них считать не следует.

decimal же напротив очень точный, но медленный.

В чем разница между float и double в Java?

Какая еще есть разница между типами данных float и double или я что-то в упор не вижу?

Отслеживать
14.2k 1 1 золотой знак 21 21 серебряный знак 31 31 бронзовый знак
задан 18 июл 2017 в 21:19
Yuri Migushin Yuri Migushin
61 1 1 серебряный знак 7 7 бронзовых знаков

Вставляйте код прямо в сообщение (в виде кода), а не ссылайтесь на внешние ресурсы. Сообщения должны быть самодостаточными, ссылки могут служить только дополнением.

18 июл 2017 в 22:46

1 ответ 1

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

Принципиальный нюанс здесь в том, что вы оперируете десятичными числами, а float и double — бинарные. Те числа, которые вы делите и получаете в результате, непредставимы в бинарной системе счисления без периодичных дробей. Подробнее:

То, что вы наблюдаете — это не округления и обрубания, а попытки компьютера впихать невпихуемое и сделать вид, что на самом деле всё в порядке. Так как количество битов у мантиссы и экспоненты типов float и double разная, то «округления» и «обрубания» будут происходить с вашей точки зрения «непредсказуемо». Эта ситуация усугубляется ещё и тем, что точность вычислений на совести процессора, который, вообще говоря, не обязан выдавать точность до последнего знака. На другом компьютере вы можете увидеть другие результаты — если не включите специальный «предсказуемый» режим, который медленнее. Но даже в этом случае вы получите только одинаковые, но «непредсказуемые» результаты на разных компьютерах.

Когда работаете с float и double, примите как данность, что они всегда с погрешностью.

Вещественные типы (double, float)

Вещественные типы (или типы с плавающей точкой) представляют значения, имеющие дробную часть. В языке MQL4 есть два типа для чисел с плавающей точкой. Способ представления вещественных чисел в машинной памяти определен стандартом IEEE 754 и не зависит от платформ, операционных систем и языков программирования.

Размер в байтах

Минимальное положительное значение

Имя double означает, что точность этих чисел вдвое превышает точность чисел типа float . В большинстве случаев тип double является наиболее удобным. Ограниченной точности чисел float во многих случаях попросту недостаточно. Причина, по которой тип float все еще используется, — экономия памяти при хранении (это важно для больших массивов вещественных чисел).

Константы с плавающей точкой состоят из целой части, точки (.) и дробной части. Целая и дробная части представляют собой последовательности десятичных цифр.

double a= 12.111 ;
double b=- 956.1007 ;
float c = 0.0001 ;
float d = 16 ;

Существует научный способ записи вещественных констант, зачастую этот способ записи более компактный, чем традиционный.

double c1=1.12123515e-25;
double c2=0.000000000000000000000000112123515; // 24 нуля после десятичной точки

Print ( «1. c1 = » , DoubleToString (c1,16));
// Результат: 1. c1 = 0.0000000000000000

Print ( «2. c1 = » , DoubleToString (c1,-16));
// Результат: 2. c1 = 1.1212351499999999e-025

Print ( «3. c2 = » , DoubleToString (c2,-16));
// Результат: 3. c2 = 1.1212351499999999e-025

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

Например, числа 0.3 и 0.7 представлены в компьютере бесконечными дробями, в то время как число 0.25 хранится точно, так как представляет из себя степень двойки.

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

void OnStart ()
<
//—
double three=3.0;
double x,y,z;
x=1/three;
y=4/three;
z=5/three;
if (x+y==z) Print ( «1/3 + 4/3 == 5/3» );
else Print ( «1/3 + 4/3 != 5/3» );
// Результат: 1/3 + 4/3 != 5/3
>

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

bool EqualDoubles( double d1, double d2, double epsilon)
<
if (epsilon <0) epsilon=-epsilon;
//—
if (d1-d2>epsilon) return false;
if (d1-d2 <-epsilon) return false;
//—
return true ;
>
void OnStart ()
<
double d_val=0.7;
float f_val=0.7;
if (EqualDoubles(d_val,f_val,0.000000000000001)) Print (d_val, «equals» ,f_val);
else Print ( «Different: d_val = » , DoubleToString (d_val,16),
» f_val = » , DoubleToString (f_val,16));
// Результат: Different: d_val= 0.7000000000000000 f_val= 0.6999999880790710
>

Необходимо отметить, что значение параметра epsilon в приведенном примере не может быть меньше предопределенной константы DBL_EPSILON. Значение этой константы 2.2204460492503131e-016. Для типа float соответствующая константа FLT_EPSILON = 1.192092896e-07. Смысл этих значений таков, что это наименьшее значение, удовлетворяющее условию 1.0+DBL_EPSILON != 1.0 (для чисел типа float 1.0+FLT_EPSILON != 1.0).

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

bool CompareDoubles( double number1, double number2)
<
if ( NormalizeDouble (number1-number2,8)==0) return ( true );
else return ( false );
>
void OnStart ()
<
double d_val=0.3;
float f_val=0.3;
if (CompareDoubles(d_val,f_val)) Print (d_val, «equals» ,f_val);
else Print ( «Different: d_val = » , DoubleToString (d_val,16),
» f_val = » , DoubleToString (f_val,16));
// Результат: Different: d_val= 0.3000000000000000 f_val= 0.3000000119209290
>

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

double abnormal = MathArcsin (2.0);
Print ( «MathArcsin(2.0) =» ,abnormal);
// Результат: MathArcsin(2.0) = -1.#IND

Кроме минус бесконечности существуют плюс бесконечность и NaN (не число). Чтобы определить, что данное число недействительно, можно использовать функцию MathIsValidNumber(). По стандарту IEEE они имеют специальное машинное представление. Например, плюс бесконечность для типа double имеет битовое представление 0x7FF0 0000 0000 0000.

struct str1
<
double d;
>;
struct str2
<
long l;
>;

//— начнем
str1 s1;
str2 s2;
//—
s1.d= MathArcsin (2.0); // получим недействительное число -1.#IND
s2=s1;
printf ( «1. %f %I64X» ,s1.d,s2.l);
//—
s2.l=0xFFFF000000000000; // недействительное число -1.#QNAN
s1=s2;
printf ( «2. %f %I64X» ,s1.d,s2.l);
//—
s2.l=0x7FF7000000000000; // наиобльшее нечисло SNaN
s1=s2;
printf ( «3. %f %I64X» ,s1.d,s2.l);
//—
s2.l=0x7FF8000000000000; // наименьшее нечисло QNaN
s1=s2;
printf ( «4. %f %I64X» ,s1.d,s2.l);
//—
s2.l=0x7FFF000000000000; // наибольшее нечисло QNaN
s1=s2;
printf ( «5. %f %I64X» ,s1.d,s2.l);
//—
s2.l=0x7FF0000000000000; // плюс бесконечность 1.#INF и наименьшее нечисло SNaN
s1=s2;
printf ( «6. %f %I64X» ,s1.d,s2.l);
//—
s2.l=0xFFF0000000000000; // минус бесконечность -1.#INF
s1=s2;
printf ( «7. %f %I64X» ,s1.d,s2.l);
//—
s2.l=0x8000000000000000; // отрицательный ноль -0.0
s1=s2;
printf ( «8. %f %I64X» ,s1.d,s2.l);
//—
s2.l=0x3FE0000000000000; // 0.5
s1=s2;
printf ( «9. %f %I64X» ,s1.d,s2.l);
//—
s2.l=0x3FF0000000000000; // 1.0
s1=s2;
printf ( «10. %f %I64X» ,s1.d,s2.l);
//—
s2.l=0x7FEFFFFFFFFFFFFF; // наибольшее нормализованное число (MAX_DBL)
s1=s2;
printf ( «11. %.16e %I64X» ,s1.d,s2.l);
//—
s2.l=0x0010000000000000; // наименьшее положительное нормализованное (MIN_DBL)
s1=s2;
printf ( «12. %.16e %.16I64X» ,s1.d,s2.l);
//—
s1.d=0.7; // покажем, что число 0.7 – бесконечная дробь
s2=s1;
printf ( «13. %.16e %.16I64X» ,s1.d,s2.l);
/*
1. -1.#IND00 FFF8000000000000
2. -1.#QNAN0 FFFF000000000000
3. 1.#SNAN0 7FF7000000000000
4. 1.#QNAN0 7FF8000000000000
5. 1.#QNAN0 7FFF000000000000
6. 1.#INF00 7FF0000000000000
7. -1.#INF00 FFF0000000000000
8. -0.000000 8000000000000000
9. 0.500000 3FE0000000000000
10. 1.000000 3FF0000000000000
11. 1.7976931348623157e+308 7FEFFFFFFFFFFFFF
12. 2.2250738585072014e-308 0010000000000000
13. 6.9999999999999996e-001 3FE6666666666666
*/

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

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