Короче говоря, мы можем знать, что плавающее число равно нулю точно, если мы знаем, что оно представляет формат.
На практике , мы сравниваем x
с небольшим номером.И если x
меньше этого числа, мы думаем, что x
такое же, как ZERO функционально (но в большинстве случаев наше маленькое число все еще больше нуля).Этот метод очень прост, эффективен и может работать на разных платформах.
На самом деле , float
и double
представлены в специальном формате, и широко используемым является IEEE 754 в текущем оборудовании, котороеразделил число на биты знака, экспоненты и мантиссы (значимого).
Итак, если мы хотим проверить, точно ли число с плавающей точкой равно НУЛЬ , мы можем проверить, является ли экспонента и мантиссаНОЛЬ, см. здесь .
В двоичных числах IEEE 754 с плавающей запятой нулевые значения представлены смещенным показателем степени и значимы, и оба равны нулю.Отрицательный ноль имеет бит знака, установленный в единицу.
Возьмем, к примеру, float
, мы можем написать простой код, чтобы извлечь бит экспоненты и мантиссы, а затем проверить его.
#include <stdio.h>
typedef union {
float f;
struct {
unsigned int mantissa : 23;
unsigned int exponent : 8;
unsigned int sign : 1;
} parts;
} float_cast;
int isZero(float num) {
int flag = 0;
float_cast data;
data.f = num;
// Check both exponent and mantissa parts
if(data.parts.exponent == 0u && data.parts.mantissa == 0u) {
flag = 1;
} else {
flag = 0;
}
return(flag);
}
int main() {
float num1 = 0.f, num2 = -0.f, num3 = 1.2f;
printf("\n is zero of %f -> %d", num1, isZero(num1));
printf("\n is zero of %f -> %d", num2, isZero(num2));
printf("\n is zero of %f -> %d", num3, isZero(num3));
return(0);
}
Результаты теста:
# равно нулю 0,000000 -> 1
# равно нулю -0,000000 -> 1
# равно нулю 1.200000 -> 0
Дополнительные примеры:
Давайте проверим, когда float
станет действительным НУЛЕМ с кодом.
void test() {
int i =0;
float e = 1.f, small = 1.f;
for(i = 0; i < 40; i++) {
e *= 10.f;
small = 1.f/e;
printf("\nis %e zero? : %d", small, isZero(small));
}
return;
}
is 1.0000e-01 zero? : NO
is 1.0000e-02 zero? : NO
is 1.0000e-03 zero? : NO
is 1.0000e-04 zero? : NO
is 1.0000e-05 zero? : NO
is 1.0000e-06 zero? : NO
is 1.0000e-07 zero? : NO
is 1.0000e-08 zero? : NO
is 1.0000e-09 zero? : NO
is 1.0000e-10 zero? : NO
is 1.0000e-11 zero? : NO
is 1.0000e-12 zero? : NO
is 1.0000e-13 zero? : NO
is 1.0000e-14 zero? : NO
is 1.0000e-15 zero? : NO
is 1.0000e-16 zero? : NO
is 1.0000e-17 zero? : NO
is 1.0000e-18 zero? : NO
is 1.0000e-19 zero? : NO
is 1.0000e-20 zero? : NO
is 1.0000e-21 zero? : NO
is 1.0000e-22 zero? : NO
is 1.0000e-23 zero? : NO
is 1.0000e-24 zero? : NO
is 1.0000e-25 zero? : NO
is 1.0000e-26 zero? : NO
is 1.0000e-27 zero? : NO
is 1.0000e-28 zero? : NO
is 1.0000e-29 zero? : NO
is 1.0000e-30 zero? : NO
is 1.0000e-31 zero? : NO
is 1.0000e-32 zero? : NO
is 1.0000e-33 zero? : NO
is 1.0000e-34 zero? : NO
is 1.0000e-35 zero? : NO
is 1.0000e-36 zero? : NO
is 1.0000e-37 zero? : NO
is 1.0000e-38 zero? : NO
is 0.0000e+00 zero? : YES <-- 1e-39
is 0.0000e+00 zero? : YES <-- 1e-40