Rappresentazione di tipi in virgola mobile

Aug 24 2020

std::numeric_limits<float>::is_iec559+ è std::numeric_limits<float>::digits == 24sufficiente per garantire (1) che floatsia binary32(2) in IEEE 754? Lo stesso per double con ... cifre == 53 ?

  1. In ogni caso comprese le implementazioni più strane pur rispettando lo standard C++.
  2. "binary32" è una rappresentazione specifica di virgola mobile nello standard IEEE 754, non intendo "memorizzata a 32 bit".

Modifica: +std::numeric_limits<float>::max_exponent - 1 == 127

Modifica: ci sono altri modi? Se sì, qual è "il migliore"?

Risposte

nop666 Aug 24 2020 at 14:24

Puoi usare la classe dei tratti per verificare che la tua rappresentazione corrisponda ad alcune aspettative.

Ecco i tratti utilizzati per testare la tua rappresentazione:

namespace num {
    template <std::size_t N> struct ieee754_traits;
    
    template <> struct ieee754_traits<4> {
      using unsigned_type = uint32_t;
      static constexpr std::size_t sign_size = 1;
      static constexpr std::size_t exp_size = 8;
      static constexpr std::size_t mant_size = 23;
      static constexpr std::size_t exp_shift = 127;
      static constexpr int32_t exp_mask = 0xFF;
      static constexpr unsigned_type mant_mask = 0x7FFFFF;
    };
    
    template <> struct ieee754_traits<8> {
      using unsigned_type = uint64_t;
      static constexpr std::size_t sign_size = 1;
      static constexpr std::size_t exp_size = 11;
      static constexpr std::size_t mant_size = 52;
      static constexpr std::size_t exp_shift = 1023;
      static constexpr int32_t exp_mask = 0x7FF;
      static constexpr unsigned_type mant_mask = 0xFFFFFFFFFFFFF;
    };

    template<typename T>
    constexpr bool check_ieee754() {
        // add more check here
        return std::numeric_limits<T>::digits == (num::ieee754_traits<sizeof(T)>::mant_size + 1) &&
           std::numeric_limits<T>::max_exponent == (num::ieee754_traits<sizeof(T)>::exp_mask - num::ieee754_traits<sizeof(T)>::exp_shift);
    }
}

Quindi, puoi controllare la tua rappresentazione:

static_assert(sizeof(float) == 4 && sizeof(double) == 8);
static_assert(num::check_ieee754<float>(), "does not match ieee754");
static_assert(num::check_ieee754<double>(), "does not match ieee754");
1 MSalters Aug 24 2020 at 15:11

Se capisco correttamente la tua domanda, si riduce a "ci sono altri formati IEC559/IEEE754 oltre ai binary32quali hanno anche una mantissa a 24 bit"? La risposta è no.

Hai bisogno della iec559parte in quanto è ciò che collega lo standard C ++ allo standard IEC. Senza di esso, tutto va bene. Sapendo che è IEC559, il digitstest è semplice.

Ma vuoi assicurarti che il "24" sia effettivamente contato in bit, quindi dovresti controllare radix==2anche tu. Questo è il binario in binary32. In alternativa, puoi controllare se sizeof(float)*CHAR_BIT==32. Se radixè maggiore di due, non puoi inserire 24 cifre in 32 bit.