Frage

Ich weiß, scheint die Frage seltsam. Programmierer denken manchmal zu viel. Bitte lesen Sie weiter ...

In C verwende ich signed und unsigned ganze Zahlen viel. Ich mag die Tatsache, dass der Compiler mich warnt, wenn ich Dinge wie eine Ganzzahl mit Vorzeichen auf eine unsigned Variablen zugewiesen wird. Ich erhalte Warnungen, wenn ich mit unsignierten ganzen Zahlen und viel viel mehr unterzeichnet vergleichen.

Ich mag diese Warnungen. Sie helfen mir, meinen Code korrekt zu halten.

Warum gehen wir nicht den gleichen Luxus für Schwimmer? Eine Quadrat-Wurzel wird auf jeden Fall nie eine negative Zahl zurück. Es gibt andere Orte auch, wo ein negativer Float-Wert keine Bedeutung hat. Perfekter Kandidat für einen unsigned Schwimmer.

Btw - Ich bin nicht wirklich daran interessiert, über das einzige Extra an Präzision, die ich durch das Entfernen des Vorzeichenbits von den Schwimmern konnte. Ich bin super zufrieden mit floats wie sie jetzt sind. Ich würde wie auf einen Schwimmer als unsigned markiert manchmal und die gleiche Art von Warnungen erhalten, die ich mit ganzen Zahlen erhalten.

Ich bin mir nicht bewusst, jeder Programmiersprache, die unsigned Gleitkommazahlen unterstützt.

Jede Idee, warum sie nicht existieren?


EDIT:

Ich weiß, dass der x87-FPU keine Anweisungen mit unsigned Schwimmer zu tun hat. Lets verwenden nur die signierten Schwimmer Anweisungen. Missbrauch (zum Beispiel unter Null gehen) nicht definiertes Verhalten in gleicher Weise in Betracht gezogen werden könnte als Überlauf von signierten ganzen Zahlen ist nicht definiert.

War es hilfreich?

Lösung

Warum C ++ keine Unterstützung für unsigned Schwimmer hat, weil es keine entsprechenden Maschinencode-Operationen für die CPU auszuführen. So wäre es sehr ineffizient sein, sie zu unterstützen.

Wenn C ++ tut es unterstützt, dann würden Sie manchmal mit einem unsigned Schwimmer sein und nicht ahnend, dass Ihre Leistung hat gerade getötet worden. Wenn C ++ es unterstützt, dann würde jeder Gleitkommaoperation müssen geprüft werden, um zu sehen, ob es signiert ist oder nicht. Und für Programme, die Millionen von Gleitkomma-Operationen zu tun, ist dies nicht akzeptabel.

So ist die Frage, warum nicht Hardware wäre Implementierer unterstützen es. Und ich denke, die Antwort darauf ist, dass es kein unsigned float Standard ursprünglich definiert war. Da Sprachen wie rückwärtskompatibel sein, auch wenn es hinzugefügt wurden Sprachen können nicht davon Gebrauch machen. Um die Floating-Point-spec zu sehen, sollten Sie auf der IEEE-Standard 754 Gleitkommatypen .

können Sie erhalten um nicht eine unsignierte Gleitkommatyps obwohl, indem eine unsigned float-Klasse erstellen, die einen Schwimmer oder Doppel und werfen Warnungen kapseln, wenn Sie in einer negativen Zahl zu passieren versuchen. Dies ist weniger effizient, aber wahrscheinlich, wenn Sie sich nicht mit ihnen intensiv werden Sie nicht über diesen leichten Leistungsverlust sorgen.

ich auf jeden Fall sehen die Nützlichkeit eines unsignierten float zu haben. Aber C / C ++ neigt Effizienz zu wählen, die am besten für jeden über Sicherheit funktioniert.

Andere Tipps

Es gibt einen signifikanten Unterschied zwischen mit und ohne Vorzeichen ganze Zahlen in C / C ++:

value >> shift

signierte Werte verlassen das oberste Bit unverändert (Vorzeichen verlängern), unsigned Werte die obere Bit löschen.

Der Grund gibt es keine unsigned float ist, dass Sie schnell in alle möglichen Probleme stoßen, wenn es keine negativen Werte sind. Bedenken Sie:

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

Welchen Wert hat c haben? -8. Aber was wäre das ohne negative Zahlen in einem System bedeuten. FLOAT_MAX - 8 vielleicht? Eigentlich, das nicht als FLOAT_MAX arbeiten - 8 FLOAT_MAX durch Präzisions Effekte so sind die Dinge noch mehr verrückt. Was, wenn es Teil eines komplexeren Ausdruck:

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

Das ist kein Problem für ganze Zahlen aufgrund der Art des Komplementsystems der 2.

Sehen Sie sich auch mathematische Standardfunktionen: sin, cos und tan nur für die Hälfte ihrer Eingangswerte arbeiten würden, könnten Sie nicht das Protokoll der Werte finden <1, könnten Sie nicht quadratische Gleichungen lösen: x = (-b + / - root (bb - 4.ac)) / 2.a, und so weiter. In der Tat wäre es wahrscheinlich für jede komplexe Funktion nicht funktionieren, da diese als Polynomapproximationen umgesetzt werden dazu neigen, die irgendwo negative Werte verwenden würden.

So sind unsigned schwimmt ziemlich nutzlos.

Aber das bedeutet nicht, zu sagen, dass eine Klasse, die Kontrollen im Bereich Wert schweben ist nicht sinnvoll, sollten Sie Werte klemmen zu einem bestimmten Bereich, beispielsweise RGB-Berechnungen.

(Nebenbei, Perl 6 können Sie schreiben

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

und dann können Sie Nonnegative::Float wie würden Sie eine andere Art verwendet werden.)

Es gibt keine Hardware-Unterstützung für nicht signiert Gleitkommaoperationen, so C es nicht bieten. C wird meist als „portable assembly“ entworfen, das heißt, so nah an das Metall, wie Sie ohne gebunden an eine bestimmte Plattform sein kann.

[Bearbeiten]

C ist wie Montage: Was Sie sehen, ist genau das, was man bekommt. Eine implizite „Ich werde prüfen, ob dieser Schwimmer ist nicht negative für Sie“ geht gegen seine Design-Philosophie. Wenn Sie es wirklich wollen, können Sie assert(x >= 0) oder ähnliches hinzufügen, aber Sie müssen das explizit tun.

Ich glaube, die unsigned int für einen größeren Wert Marge wegen der Notwendigkeit geschaffen wurde als die signed int bieten konnte.

Ein Schwimmer hat einen viel größeren Spielraum, so gibt es nie ein ‚physischen‘ müssen für einen nicht signierten Schwimmer. Und wie Sie sich in Ihrer Frage darauf hin, die zusätzliche 1-Bit-Präzision ist nichts zu töten.

Edit: die Antwort von Brian R. Bondy Nach der Lektüre, ich habe zu ändern, meine Antwort: Er ist auf jeden Fall richtig, dass der zugrunde liegende CPUs nicht unsigned float Operationen hat. Allerdings bleibe ich meine Überzeugung, dass dies eine Design-Entscheidung war die Gründe auf Basis von I oben angegeben; -)

Ich denke, Treb auf dem richtigen Weg ist. Es ist wichtiger für ganze Zahlen, die Sie einen nicht signierten entsprechenden Typen. Das sind diejenigen, die in verwendet werden Bitverschiebung und verwendet in Bit-Karten . Ein Vorzeichenbit wird einfach in den Weg. Um beispielsweise einen negativen Wert Rechtsverschieben, ist der sich ergebende Wert Implementierung in C ++ definiert. Dadurch, dass mit einem unsigned integer oder so einer überquell hat Semantik perfekt definiert, weil es so etwas in der Art und Weise ist.

Also für ganze Zahlen zumindest die Notwendigkeit eines separaten Typen ohne Vorzeichen ist stärker als nur geben Warnungen. Alle oben genannten Punkte brauchen nicht für Schwimmer in Betracht gezogen werden. So gibt es, glaube ich, keine wirkliche Notwendigkeit für Hardware-Unterstützung für sie, und C wird bereits sie nicht an diesem Punkt unterstützen.

Ich denke, es hängt davon ab, dass die IEEE floating Punkte Spezifikationen nur angemeldet sind und dass die meisten Programmiersprachen verwenden sie.

wikipedia articla auf ieee Gleitkommazahlen

Edit:. Auch, wie andere bereits erwähnt, die meisten Hardware nicht nicht-negativen Schwimmer nicht unterstützt, so dass die normale Art von Schwimmern effizienter zu machen sind, da Hardware-Unterstützung ist

  

Ein Quadratwurzel wird auf jeden Fall nie eine negative Zahl zurück. Es gibt andere Orte auch, wo ein negativer Float-Wert keine Bedeutung hat. Perfekter Kandidat für einen unsigned Schwimmer.

C99 unterstützt komplexe Zahlen, und eine Art generische Form von sqrt, so wird sqrt( 1.0 * I) negativ sein.


Die commentors markiert einen leichten Glanz oben, dass ich mit Bezug auf den Typ-generic sqrt Makro anstatt die Funktion, und es wird eine skalare Fließkommawert durch Abschneiden des Komplexes in seine reale Komponente zurück:

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

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

    double f = sqrt(a);

    return 0;
}

Es enthält auch eine Gehirn-fart, als der Realteil des sqrt jeder komplexen Zahl positiv oder Null ist, und sqrt (1,0 * I) ist sqrt (0,5) + sqrt (0,5) * I nicht -1.0.

Ich denke, der Hauptgrund ist, dass unsigned Schwimmer hätte wirklich beschränkten Verwendungen im Vergleich zu unsigned ints. Ich kaufe nicht das Argument, dass es ist, weil die Hardware nicht unterstützt wird. Ältere Prozessoren hatte keine Gleitkommapräzision überhaupt, es war alles in Software emuliert. Wenn unsigned Schwimmer nützlich wären, würden sie in Software implementiert wurden erste und die Hardware würde nachgezogen haben.

Unsigned Integer-Typen in C sind in einer solchen Art und Weise definiert, wie die Regeln eines abstrakten algebraischen Ring zu gehorchen. Zum Beispiel für einen beliebigen Wert X und Y, das Hinzufügen XY Y wird X. Unsigned Integer-Typen sind garantiert diese Regeln in allen Fällen zu gehorchen, die nicht beinhalten Umwandlung in oder aus einem anderen numerischen Typ [oder unsigned Typen unterschiedlicher Größen] ergeben und diese Sicherheit ist eines der wichtigsten Merkmal solcher Typen. In einigen Fällen ist es sinnvoll, die Möglichkeit zu geben, bis zu negativen Zahlen im Austausch für die zusätzliche Garantien nur unsigned Typen darstellen zur Verfügung stellen können. Gleitkommatypen, ob signiert oder nicht, kann nicht befolgen alle Regeln eines algebraischen Ring [z sie können nicht, dass X garantieren + Y-Y wird gleich X], und zwar IEEE erlaubt es nicht, auch sie nach den Regeln einer Äquivalenzklasse zu halten [durch die Forderung, dass bestimmte Werte selbst ungleich vergleichen]. Ich glaube nicht, ein „unsigned“ Gleitkommatyp durch irgendwelche Axiome halten könnte, die ein gewöhnlicher Gleitkommatyp nicht konnte, so bin ich nicht sicher, welche Vorteile es böte.

Ich vermute, es liegt daran, dass die zugrunde liegenden Prozessoren von C-Compiler gezielt nicht über eine gute Art und Weise des Umgangs mit unsigned Gleitkommazahlen haben.

IHMO es ist, weil beide mit und ohne Vorzeichen unterstützt Gleitkommatypen in Hardware oder Software zu umständlich wäre,

Für Integer-Typen können wir die gleiche Logikeinheit für beide mit und ohne Vorzeichen Integer-Operationen in den meisten Situationen die schöne Eigenschaft von 2-Komplement zu verwenden, da ist identisch in den Fällen für add, sub, nicht-Erweiterung mul und die meisten Bit-Operationen. Für Operationen, die zwischen mit und ohne Vorzeichen Version unterscheiden können wir immer noch teilen sich die Mehrheit der Logik . Zum Beispiel

  • Arithmetik und logische Verschiebung braucht nur eine geringfügige Änderung der Füllstoff für die oberen Bits
  • Multiplikation Widening kann die gleiche Hardware für den Hauptteil verwenden und dann einige getrennte Logik anpassen das Ergebnis der signness zu ändern . Nicht, dass es in Echt Multiplikatoren verwendet wird, aber es ist möglich zu tun
  • Signed Vergleich kann durch Umschalten des Top-Bit oder Hinzufügen INT_MIN kehrt leicht zu unsigned Vergleich und umgerechnet werden. Auch theoretisch möglich, ist es wahrscheinlich nicht auf Hardware verwendet, aber es ist sinnvoll auf Systemen, die nur eine Art von Vergleich unterstützen (wie 8080 oder 8051)

Systeme, die auch 1-Komplement benötigen nur eine kleine Änderung an die Logik, weil es einfach das Übertragsbit ist zu dem niedrigstwertigen Bit umschlungen. Nicht sicher Vorzeichen-Größen-Systeme, aber es scheint, wie sie href="https://en.wikipedia.org/wiki/Signed_number_representations#History" rel="nofollow verwenden 1-Komplement intern so die Gleiches gilt

Leider wir nicht, dass Luxus für Gleitkommatypen. Mit dem einfach das Vorzeichenbit befreien wir die unsignierte Version haben werden. Aber was sollten wir nutzen, dass etwas für?

  • Erhöhen Sie den Bereich, indem es den Exponenten Hinzufügen
  • Erhöhen Sie die Genauigkeit, indem sie es auf die Mantisse hinzufügen. Dies ist oft nützlich, da wir in der Regel mehr Präzision als Bereich benötigen

Aber beide Entscheidungen brauchen einen größer Addierer für den breiteren Wertebereich gerecht zu werden. Das erhöht die Komplexität der Logik, während das oberste Bit des Addierer sitzt ungenutzt die meiste Zeit. Noch mehr Schaltungen für Multiplikationen, Divisionen oder andere komplexe Operationen benötigt werden,

Auf Systemen, die Software verwenden, Floating-Point benötigen Sie 2 Versionen für jede Funktion, die nicht erwartet wurde, während die Zeitspeicher so viel teuer waren, oder man müßte etwas „tricky“ Weg finden Teile des signierten zu teilen und unsigned Funktionen

Allerdings Gleitkomma-Hardware lange existierte, bevor C erfunden wurde, so ich glaube, die Wahl in C auf den Mangel an Hardware-Unterstützung zurückzuführen war wegen des Grundes, warum ich oben

erwähnt

Wie gesagt, gibt es mehr spezialisiert unsigned Gleitkommaformate, vor allem für Bildverarbeitungszwecke, wie der Khronos Gruppe 10 und 11-Bit-Fließkommatyp

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top