Как можно определить значение и ширину в битах типа float, double: есть ли стандартное определение? - PullRequest
0 голосов
/ 03 июля 2019

Существует ли стандартный способ определения ширины значения и двойного в C или C ++? Мне известно, что двойной формат IEEE-754 хранит значения в 53 битах, но я бы не хотел использовать «магическое» число в моем коде.

В Linux существует файл usr/include/ieee754.h, но он описывает формат с использованием битовых полей в структуре, размер которой я не могу определить (во время компиляции).

Допустимо только Linux-решение.

Ответы [ 3 ]

2 голосов
/ 03 июля 2019

Существует ли стандартный способ определения мантиссы двойного числа?

Вы готовы принять решение для Linux, но вы утверждаете, что заголовок ieee754.h glibc делаетне соответствует вашим потребностям, поэтому я пришел к выводу, что проблема, которую вы пытаетесь решить, заключается не в извлечении или передаче самих битов, поскольку union ieee_double этого заголовка даст вам возможность сделать это.

Я прочитал "мантисса "как нечто отличное от" количества бит мантиссы ", поэтому я прихожу к выводу, что DBL_MANT_DIG из float.h тоже не то, что вы ищете.

Единственная другая вещь, которую яможно думать о том, что вы можете иметь в виду значение значимого (мантиссы) в соответствии со стандартной моделью с плавающей запятой:

v = ( знак) * значимое и * основание показатель степени

Функция frexp()в стандарте языка C, начиная с C99, служит этой цели. 1 Он разделяет double iк показателю степени (из 2) и значению, представленному как double.Для конечного ненулевого ввода абсолютное значение результата находится в полуоткрытом интервале [0,5, 1).

Пример :

#include <math.h>
#include <stdio.h>

void print_parts(double d) {
    int exp;
    double significand = frexp(d, &exp);

    printf("%e = %f * 2^%d\n", d, significand, exp);
}

Примеры выходных данных :

7.256300e + 16 = 0.503507 * 2 ^ 571.200000e-03 = 0,614400 * 2 ^ -9-0.000000e + 00 = -0.000000 * 2 ^ 0

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


1 Технически, frexp() служит цели , при условии, что FLT_RADIX расширяется до 2. Это хорошо определено в любом случае, но если ваше представление double использует другое основание, то результат frexp(), хотя он и четко определен, вероятно, не тот, который вы ищете.

2 голосов
/ 05 июля 2019

В C ++ вы можете использовать std::numeric_limits<double>::digits и std::numeric_limits<float>::digits:

#include <limits>
#include <iostream>

int main()
{
    std::cout << std::numeric_limits<float>::digits << "\n";
    std::cout << std::numeric_limits<double>::digits << "\n";
}

отпечатки

24
53

соответственно.

2 голосов
/ 03 июля 2019

Используйте FLT_MANT_DIG и DBL_MANT_DIG, определенные в <float.h>:

#include <float.h>
#include <stdio.h>


#if FLT_RADIX != 2
    #error "Floating-point base is not two."
#endif


int main(void)
{
    printf("There are %d bits in the significand of a float.\n",
        FLT_MANT_DIG);
    printf("There are %d bits in the significand of a double.\n",
        DBL_MANT_DIG);
}
...