Domanda

So che la domanda sembra strana.I programmatori a volte pensare troppo.Continua a leggere...

In C io uso signed e unsigned numeri interi molto.Mi piace il fatto che il compilatore mi avvisa se faccio le cose per come l'assegnazione di un valore integer senza segno variabile.Ricevo avvisi se confronto firmato con numeri interi senza segno e molto molto di più.

Mi piacciono questi avvisi.Mi aiutano a mantenere il mio codice corretto.

Perché non abbiamo la stessa di lusso per i galleggianti?Una radice quadrata sarà sicuramente mai restituire un numero negativo.Ci sono altri posti dove in negativo, il valore del galleggiante non ha alcun significato.Candidato perfetto per un unsigned galleggiante.

Btw - io non sono davvero appassionato a singolo bit di precisione, che ho potuto ottenere rimuovendo il bit di segno dai carri.Sono super felice con floats come sono adesso.Vorrei solo segno di un galleggiante come unsigned a volte e ottenere lo stesso tipo di avvertimenti che ho con i numeri interi.

Io non sono a conoscenza di alcun linguaggio di programmazione che supporta unsigned numeri a virgola mobile.

Qualche idea del perché non esistono?


EDIT:

So che il 87 x FPU non ha le istruzioni per affrontare unsigned carri allegorici.Consente di utilizzare solo il sottoscritto float istruzioni.L'uso improprio (ad es.andando sotto zero) potrebbe essere considerato comportamenti indefiniti nello stesso modo come overflow di valori integer con segno è definito.

È stato utile?

Soluzione

Perché C ++ non ha il supporto per i galleggianti non firmati è perché non ci sono operazioni in codice macchina equivalenti per la CPU da eseguire. Quindi sarebbe molto inefficiente per sostenerlo.

Se C ++ ha fatto sostenerlo, allora si sarebbe a volte utilizzando un galleggiante non firmato e non rendendosi conto che le prestazioni è appena stato ucciso. Se C ++ supportato allora ogni operazione in virgola mobile avrebbe bisogno di essere controllato per vedere se è firmato o meno. E per programmi che fanno milioni di operazioni in virgola mobile, questo non è accettabile.

Quindi, la questione sarebbe il motivo per cui non gli esecutori di hardware supportano. E credo che la risposta è che non vi era alcuna norma galleggiante non firmato definita in origine. Dal momento che lingue come di essere retrocompatibile, anche se sono stati aggiunti lingue non hanno potuto fare uso di esso. Per vedere il punto di spec flottante si dovrebbe guardare il standard IEEE 754 in virgola mobile .

Si può andare in giro non avendo un tipo unsigned virgola mobile anche se con la creazione di una classe galleggiante non firmato che incapsula un float o doppio e lancia avvisi se si tenta di passare in un numero negativo. Questo è meno efficiente, ma probabilmente se non vengono utilizzati intensamente che non si cura di quella leggera perdita di prestazioni.

Sono assolutamente vedere l'utilità di avere un flottante non firmato. Ma C / C ++ tende a scegliere l'efficienza che funziona meglio per tutti oltre la sicurezza.

Altri suggerimenti

C'è una differenza significativa tra numeri interi con e senza segno in C / C ++:

value >> shift

valori con segno lasciano il bit superiore invariato (segno estendere), valori senza segno cancellare il bit superiore.

Il motivo non v'è alcuna float non firmato è che si esegue rapidamente in tutti i tipi di problemi se non ci sono valori negativi. Considerate questo:

float a = 2.0f, b = 10.0f, c;
c = a - b;

Che valore non c avere? -8. Ma che cosa vorrebbe dire in un sistema senza numeri negativi. FLOAT_MAX - 8 forse? A dire il vero, che non funziona come FLOAT_MAX - 8 è FLOAT_MAX a causa di effetti di precisione e quindi le cose sono ancora più irregolare. E se fosse parte di un'espressione più complessa:

float a = 2.0f, b = 10.0f, c = 20.0f, d = 3.14159f, e;
e = (a - b) / d + c;

Questo non è un problema per gli interi a causa della natura del sistema di complemento a 2.

Considera anche funzioni matematiche standard: sin, cos e tan avrebbe funzionato solo per metà delle loro valori di ingresso, non si poteva trovare il registro dei valori <1, non si poteva risolvere equazioni di secondo grado: x = (-b + / - root (bb - 4.ac)) / 2.a, e così via. In realtà, probabilmente non avrebbe funzionato per qualsiasi funzione complessa in quanto questi tendono ad essere implementato come approssimazioni polinomiali che userebbero i valori negativi da qualche parte.

Quindi, carri non firmati sono abbastanza inutile.

Ma questo non significa dire che una classe che vanno controlli galleggiano valori non è utile, si consiglia di fissare i valori per un dato intervallo, ad esempio i calcoli RGB.

(Per inciso, Perl 6 vi permette di scrivere

subset Nonnegative::Float of Float where { $_ >= 0 };

e quindi è possibile utilizzare Nonnegative::Float proprio come si farebbe con qualsiasi altro tipo.)

Non c'è alcun supporto hardware per le operazioni in virgola mobile senza segno, quindi C non lo offre. C è principalmente progettato per essere "montaggio portatile", cioè, più vicino al metallo come si può essere, senza essere legato ad una specifica piattaforma.

[modifica]

C è come il montaggio: ciò che vedi è esattamente quello che si ottiene. Un implicito "Vado a controllare che questo galleggiante è negativo per te" va contro la sua filosofia di design. Se si vuole veramente, è possibile aggiungere assert(x >= 0) o simili, ma bisogna farlo in modo esplicito.

Credo che il unsigned int è stato creato a causa della necessità di un margine valore maggiore del int firmato poteva offrire.

Un galleggiante ha un margine molto più grande, quindi non c'era mai un 'fisico' necessario per un galleggiante senza segno. E come fai notare tu stesso nella sua interrogazione, l'ulteriore precisione 1 bit è nulla di uccidere per.

Modifica Dopo aver letto la risposta href="https://stackoverflow.com/questions/512022/why-doesnt-c-have-unsigned-floats/512071#512071"> , ho di modificare la mia risposta: È sicuramente giusto che le CPU sottostanti non avevano operazioni galleggiante senza segno. Tuttavia, mantengo la mia convinzione che questa è stata una decisione di progettazione in base alle ragioni ho detto sopra; -)

Credo Treb è sulla strada giusta. E 'più importante per gli interi che avete un tipo corrispondente senza segno. Questi sono quelli che vengono utilizzati in bit-shifting e utilizzati in po-mappe . Un bit di segno ottiene solo nella via. Ad esempio, fare spostando un valore negativo, il valore risultante è definita implementazione in C ++. Farlo con un intero senza segno o fuoriuscita quali ha perfettamente definito semantica perché non esiste bit nel modo.

Quindi, per gli interi, almeno, la necessità di un tipo unsigned separata è più forte di un semplice dare avvertimenti. Tutti i punti di cui sopra non hanno bisogno di essere considerato per i galleggianti. Quindi, non v'è, credo, alcuna reale necessità di un supporto hardware per loro, e C sarà già non li sostengono in quel punto.

Credo che dipende da che le specifiche IEEE Floating Points solo sono firmati e che la maggior parte dei linguaggi di programmazione li uso.

wikipedia articla su numeri in virgola mobile IEEE

Modifica:. Inoltre, come già sottolineato da altri, la maggior parte hardware non supporta carri non negativi, in modo che il tipo normale di carri sono più efficienti di fare poiché non v'è il supporto hardware

  

Una radice quadrata sarà sicuramente mai restituire un numero negativo. Ci sono altri posti in cui un valore float negativo non ha alcun significato. candidato perfetto per un galleggiante non firmato.

C99 supporta i numeri complessi, e un tipo di forma generica sqrt, quindi sqrt( 1.0 * I) sarà negativo.


I commentors evidenziato un leggero gloss sopra, dal fatto che mi riferivo al tipo generico sqrt macro anziché la funzione, e verrà restituito un valore in virgola mobile scalare per troncamento del complesso alla sua componente reale:

#include <complex.h>
#include <tgmath.h>

int main () 
{
    complex double a = 1.0 + 1.0 * I;

    double f = sqrt(a);

    return 0;
}

Inoltre contiene un cervello-peto, come la parte reale della sqrt di ogni numero complesso è positivo o zero, e sqrt (1,0 * I) è sqrt (0,5) + sqrt (0,5) * Non -1.0.

Credo che la ragione principale è che galleggia senza segno avrebbero usi davvero limitati rispetto a unsigned int. Io non comprare l'argomento che è perché l'hardware non lo supporta. processori più vecchi non avevano capacità in virgola mobile a tutti, è stato tutto emulato nel software. Se galleggia senza segno stati utili sarebbero stati implementati nel software e l'hardware prima avrebbero seguito l'esempio.

Unsigned integer tipi in C sono definiti in modo da rispettare le regole di un'astratta algebrica anello.Per esempio, per qualsiasi valore di X e Y, l'aggiunta di X-Y di Y sarà resa X.Unsigned integer tipi sono garantiti per obbedire a queste regole in tutti i casi che non prevedono la conversione o da qualsiasi altro tipo numerico [o senza segno di dimensioni diverse), e che la garanzia è una delle caratteristiche più importanti di tali tipi.In alcuni casi, è utile per dare la possibilità di rappresentare i numeri negativi in cambio di garanzie in più solo per i tipi senza segno in grado di fornire.I tipi a virgola mobile, firmate o non possono rispettare tutte le regole di un algebrica anello [es.essi non possono garantire che X+Y-Y sarà uguale X], e, anzi, IEEE non permettono loro di rispettare le regole di una classe di equivalenza [richiedendo che certi valori confrontare impari a se stessi].Non credo che un "unsigned" tipo a virgola mobile potrebbe rispettare assiomi che un normale tipo a virgola mobile non poteva, quindi non sono sicuro di quali vantaggi avrebbe offerto.

Ho il sospetto che è perché i processori alla base di mira dai compilatori C non hanno un buon modo di trattare con i numeri in virgola mobile senza segno.

IHMO è perché supportare entrambi i tipi a virgola mobile e senza segno in hardware o software sarebbe troppo fastidioso

Per tipi interi possiamo utilizzare il stesso unità logica per sia le operazioni interi con e senza segno nella maggior parte delle situazioni utilizzando la bella proprietà di complemento a 2, perché il risultato è identico in quei casi per add, sub, mul non l'ampliamento e operazioni più bit a bit. Per le operazioni che differenziano tra la versione firmato e unsigned possiamo ancora condivido la maggior parte della logica . Ad esempio

  • aritmetica e dell'invertitore logico bisogno solo di un leggero cambiamento nel riempitivo per i bit migliori:
  • Allargamento moltiplicazione possono utilizzare lo stesso hardware per la parte principale e poi una logica separata impostare, il risultato di modificare la signness . Non che sia utilizzato in moltiplicatori reali, ma è possibile fare
  • Confronto firmato può essere convertito in confronto senza segno e viceversa facilmente commutando il href="https://stackoverflow.com/q/27527943/995714"> all'inizio bit o INT_MIN . Inoltre teoricamente possibile, è probabilmente non utilizzato su hardware, tuttavia è utile su sistemi href="https://stackoverflow.com/a/54643085/995714"> (come 8080 o 8051)

I sistemi che utilizzano il complemento 1 di anche solo bisogno di una piccola modifica alla logica, perché è semplicemente il bit di riporto avvolto intorno al bit meno significativo. Non sei sicuro di sistemi di sign-magnitudine, ma sembra che essi utilizzare complemento 1 di internamente in modo che il stessa cosa si applica

Purtroppo non lo facciamo questo lusso per i tipi in virgola mobile. Con la semplice liberando il bit di segno avremo la versione senza segno. Ma allora che cosa dovremmo usare quel po 'di?

  • aumentare la gamma aggiungendolo all'esponente
  • Aumentare la precisione aggiungendolo alla mantissa. Questo è spesso più utile, come abbiamo in genere bisogno di più precisione rispetto intervallo

Ma entrambe le scelte hanno bisogno di un più grande vipera per ospitare per il campo di valori più ampia. Che aumenta la complessità della logica, mentre bit superiore della vipera sta lì inutilizzata la maggior parte del tempo. sarà necessaria ancora di più circuiti per moltiplicazioni, divisioni o altre operazioni complesse

Sui sistemi che utilizzano il software in virgola mobile è necessario 2 versioni per ogni funzione che non era previsto nel corso del tempo la memoria era tanto costoso, o che avrebbe dovuto trovare un modo "difficile" per condividere parti del sottoscritto e le funzioni di unsigned

virgola mobile hardware esisteva molto prima C è stato inventato , così credo che la scelta in C era dovuto alla mancanza di supporto hardware a causa del motivo che ho citato sopra

Ciò detto, esistono diversi formati in virgola mobile specializzati firmate, principalmente per scopi di elaborazione delle immagini, come gruppo Khronos 10 e 11 bit a virgola mobile tipo

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top