2013-10-26 10 views
5

Sto scrivendo una classe simile a un intero che rappresenta un valore che si trova da qualche parte in un intervallo. Ad esempio, il valore di bounded::integer<0, 10> è compreso nell'intervallo [0, 10]. Per questa classe, ho definito radix come 2.Che cos'è std :: numeric_limits <T> :: cifre che si suppone rappresentino?

Quale dovrebbe essere il valore di digits per bounded::integer<-100, 5>?

Che dire di bounded::integer<16, 19>?

risposta

5

Dopo aver letto lo standard un po 'di più e aver pensato a questo, credo di avere la risposta migliore, ma non ne sono sicuro.

In primo luogo, la definizione di digits, tratto dal più recente C++ 14 progetto di norma, N3797, § 18.3.2.4:

static constexpr int digits;

8 Numero di radix cifre che può essere rappresentato senza modificare.

9 Per i tipi interi, il numero di bit senza segno nella rappresentazione.

10 Per i tipi a virgola mobile, il numero di radix cifre nella mantissa

Il caso bounded::integer<-100, 5> è lo stesso che per bounded::integer<0, 5>, che darebbe un valore di 2.

Per il caso di bounded::integer<16, 19>, digits deve essere definito come 0. Tale classe non può nemmeno rappresenta un numero 1 bit (dal 0 e 1 non sono nella gamma), e secondo 18.3.2.7.1:

Tutti i membri sono forniti per tutte le specializzazioni. Tuttavia, molti valori devono essere significativi solo in determinate condizioni (ad esempio, epsilon() è significativo solo se is_integer è false). Qualsiasi valore che non sia "significativo" deve essere impostato su 0 o falso.

credo che qualsiasi classe intero simile che non ha 0 come un possibile valore non può calcolare per significato digits e digits10.

Un'altra possibile risposta è l'utilizzo di una definizione teorica delle informazioni. Tuttavia, questo non è coerente con i valori per gli interi incorporati. La descrizione lascia esplicitamente dei bit di segno, ma quelli sarebbero comunque considerati un singolo bit di informazione, quindi sento che esclude questa interpretazione. Sembra che questa esclusione del bit di segno significhi anche che devo prendere la minore grandezza della fine negativa e la fine positiva dell'intervallo per il primo numero, motivo per cui ritengo che la prima domanda sia equivalente a bounded::integer<0, 5>. Questo perché è garantito che 2 bit possano essere memorizzati senza perdita di dati. È possibile memorizzare fino a 6 bit finché il numero è negativo, ma in generale si ottiene solo 2.

bounded::integer<16, 19> è molto più complicato, ma credo che l'interpretazione di "non significativo" ha più senso di spostamento del valore di più e dare la stessa risposta, come se fosse bounded::integer<0, 3>, che sarebbe 2.

Credo che questa interpretazione sia conforme allo standard, sia coerente con altri tipi di interi ed è la meno probabile che possa confondere gli utenti di tale classe.

Per rispondere alla domanda dei casi d'uso di digits, un commentatore ha menzionato l'ordinamento digitale. Un ordinamento per base 2 radix potrebbe aspettarsi di utilizzare il valore in digits per ordinare un numero. Questo andrebbe bene se si imposta digits su 0, poiché ciò indica una condizione di errore per il tentativo di utilizzare un ordinamento di tipo radix, ma possiamo fare meglio pur rimanendo in linea con i tipi incorporati?

Per gli interi senza segno, l'ordinamento radix che dipende dal valore di digits funziona correttamente. uint8_t ha digits == 8. Tuttavia, per interi con segno, questo non funzionerebbe: std::numeric_limits<int8_t>::digits == 7. Dovresti anche ordinare su quel bit di segno, ma lo digits non ti fornisce abbastanza informazioni per farlo.

+0

"Il secondo numero,' ranged_integer <16, 19> 'è molto più complicato," La domanda che mi chiederei è * ciò che viene 'digits' utilizzato per *? Ad esempio, potresti usarlo in un ordinamento digitale. Mi aspetto che 'digits' fornisca tutte le informazioni necessarie; eppure non per il tuo 'ranged_integer's. Non riesco a memorizzare un numero a 3 cifre in "ranged_integer <16,19>" e un ordinamento digitale sulle prime 3 cifre produrrebbe risultati errati. – dyp

+0

@DyP Mi riferivo all'ordine nella domanda. Modificherò la mia risposta per renderlo più chiaro, quindi non devi saltare avanti e indietro. Rispondere al tuo esempio di ordinamento digitale richiederà un po 'più di spazio di quello che penso di avere in un commento, quindi modificherò anche quella risposta. –

+0

Ah! Grazie per il chiarimento. – dyp

0

Stai pensando troppo. Ci sono due opzioni semplici per digits specializzazioni per il proprio ranged_integer

  • log2(Last-First) quando si rappresenta la gamma [First, Last).
  • il valore di N * numeric_limits<U>::digits che corrisponde al più piccolo archivio sottostante std::array<U, N> in cui è possibile memorizzare l'intervallo.

Si noti che la classe ranged_integer può eseguire internamente una trasformazione per mappare un intervallo di, ad es. [-100, 5] su [0, 105] in modo che non devi preoccuparti di sign-bit ecc

Problemi correlati