Warum wird Infinity in der Windows 10-Konsole als „8“ gedruckt?

146

Ich testete , was sich durch die Division mit Nullen dh zurückgegeben wurde 0/1, 1/0und 0/0. Dafür habe ich etwas Ähnliches verwendet:

Console.WriteLine(1d / 0d);

Dieser Code gibt jedoch 8keine Infinityoder eine andere Zeichenfolgenkonstante wie aus PositiveInfinity.

Der Vollständigkeit halber alle folgenden Drucke 8:

Console.WriteLine(1d / 0d);

double value = 1d / 0d;
Console.WriteLine(value);

Console.WriteLine(Double.PositiveInfinity);

Und Console.WriteLine(Double.NegativeInfinity);druckt -8.

Warum druckt diese Unendlichkeit 8?


Für diejenigen unter Ihnen, die zu denken scheinen, dass dies ein Unendlichkeitssymbol ist, nicht eine Acht, das folgende Programm:

Console.WriteLine(1d / 0d);

double value = 1d / 0d;
Console.WriteLine(value);

Console.WriteLine(Double.PositiveInfinity);

Console.WriteLine(8);

Ausgänge:

Inifinity-Ausgabe

TheLethalCoder
quelle
69
Sie sehen, ist das Zeichen der Unendlichkeit. Drehen Sie es einfach um 90 Grad, um es zu sehen. 8
Mohit Shrivastava
23
Sind Sie sicher, dass es sich um ein tatsächliches 8, nicht um ein seltsames Unicode-Zeichen für Unendlichkeit handelt, das um 90 Grad gedreht wurde? Dies kann sich je nach Gebietsschema ändern. Ich habe es auf dotnetfiddle.net versucht und es wird gedruckt Infinity.
Kroltan
4
@TheLethalCoder Bitte tun Sie, was Sinatr vorgeschlagen hat, oder drucken Sie die Ausgabe von Double.PositiveInfinity.ToString()[0] == '8'. Es gibt einige exotische Charaktere, die in einigen Schriftarten anderen sehr ähnlich sehen. Für welche Sprache ist Ihr Computer konfiguriert?
Kroltan
15
Dies scheint ein Windows 10-Problem zu sein. In Windows 8.1 hatte ich ein Unendlichkeitssymbol. Vor ein paar Tagen auf Windows 10 aktualisiert und jetzt habe ich auch ein 8(deutsches Gebietsschema).
René Vogt
13
Eine schnelle Überprüfung wäre zu sehen, was passiertConsole.Write("∞");
Jon Hanna

Antworten:

110

Stellen Sie sicher, dass der Gleitkommawert ist, +Infinitywenn der Zähler einer Gleitkommadivision durch Null positiv ist, -Infinitywenn der Zähler einer Gleitkommadivision durch Null negativ ist und NaNwenn der Zähler und der Nenner einer Gleitkommadivision beide Null sind. Dies steht in der IEEE754-Gleitkommaspezifikation , die von C # verwendet wird.

In Ihrem Fall konvertiert die Konsole das Unendlichkeitssymbol (das manchmal typografisch als horizontale 8 - ∞ dargestellt wird) in eine vertikale 8.

Bathseba
quelle
13
@ TheLethalCoder Das Bild widerlegt diese Antwort nicht, da es ein Bild Ihrer Konsole ist
Rob
9
@Rob Ich habe die Antwort falsch verstanden, aber das wirft die Fragen auf, warum konvertiert es sie in eine 8? Und warum drucken einige Geigen / Konsolen das String-Literal
TheLethalCoder
1
Dies scheint bei Verwendung des Debuggers der Fall zu sein. Ich sehe ein Unendlichkeitssymbol (dh die horizontale 8). Gibt es einen Grund, warum meine Konsole in eine 8 konvertiert wird, während alle anderen zu verwenden scheinen Infinityoder ähnliches, selbst wenn ich den Code aus der Antwort von verwende Soren durch Angabe der Kultur
TheLethalCoder
4
Es heißt "Lemniskate". Es hat einen Unicode-Wert: ∞
BlueRaja - Danny Pflughoeft
14
Dies erklärt wahrscheinlich, warum Buzz Lightyear "To Eight And Beyond!" Sagt. wenn ich Toy Story auf meinem PC spiele. ;)
DeanOC
70

Bei bestimmten Einstellungen (z. B. Kombination von Kulturen, Ausgabecodierung usw.) gibt .NET das Unicode-Unendlichkeitszeichen ∞ (∞ / & # 8734;) aus. Der Windows 10-Konsolen- / Terminalemulator zeigt (erneut bestimmte Einstellungen - siehe Abbildung unten) dieses Unicode-Zeichen als 8 an.

Unter Windows 10 wird beispielsweise mit den folgenden Einstellungen (beachten Sie die Codepage) das einfache Einfügen von ∞ in die Konsole als 8 angezeigt.

Einstellung zum Reproduzieren

BEARBEITEN

Dank des Kommentars von Chris : Es scheint, dass die Ausgabeschrift in Kombination mit der Codepage für das Problem ∞ => 8 auf der Konsole verantwortlich ist. Wie er bekomme ich in allen TrueType-Schriftarten, die ich ausprobiert habe, eine korrekte Anzeige von ∞ und sehe nur 8, wenn Raster-Schriftarten ausgewählt sind.

Schriftarteneinstellungen

tolanj
quelle
1
Meins zeigt tatsächlich das Unendlichkeitszeichen auf seiner Seite anstelle einer "8", wenn es in die Konsole eingefügt wird, obwohl ich "437 (OEM - USA)" verwende
Derek 3 會 功夫
3
Obwohl die Antwort richtig ist, dass bestimmte Einstellungen dieses Anzeigeproblem verursachen können, ist die zweite Hälfte falsch. Meine Optionen sehen derzeit genauso aus wie Ihre oben und ich erhalte das richtige ∞ anstelle einer 8. Ich kann nur dann eine 8 anzeigen, wenn ich zur Seite "Schriftarten" gehe und "Raster-Schriftarten" aus der Liste der verfügbaren Schriftarten auswähle. Consolas, Courier New und andere scheinen es alle gut zu zeigen ...
Chris
Es ist definitiv eine Kombination der beiden Faktoren, da das Symbol immer noch korrekt angezeigt wird, wenn die Schriftart auf Raster gesetzt wird, wenn die Codepage 437 ist. Nur wenn beide Bedingungen erfüllt sind, scheint dies zu geschehen (zumindest für mich).
Moshe Katz
39

Das 8Symbol tritt auf, wenn Windows Unicode in eine Legacy-Zeichencodierung konvertiert. Da die Legacy-Codierung kein Unendlichkeitssymbol enthält, wird standardmäßig eine "beste Anpassung" an dieses Symbol verwendet, in diesem Fall die Nummer 8. Siehe ein Beispiel für die "Windows-1252" -Codierung von Microsoft . Anscheinend verwendet Windows 10 in der Konsole standardmäßig noch ältere Zeichencodierungen (siehe "Codepages" ).

Peter O.
quelle
11
Ich frage mich, warum "8" als gut geeignet angesehen wird, wenn es semantisch so verwirrend ist. Andere Zeichen auf Codepage 437 scheinen besser zu passen, wie das Gradzeichen oder das Pro-Mille-Zeichen (ein% mit zwei O unter dem Schrägstrich). Keines davon wäre so gut wie ein tatsächliches Unendlichkeitszeichen, aber sie scheinen weniger anfällig für Verwirrung zu sein.
Supercat
"Anscheinend verwendet Windows 10 standardmäßig immer noch Legacy-Zeichencodierungen in der Konsole." Nein, bei meiner Windows 10 cmd.exe ist die Legacy-Codierung standardmäßig deaktiviert.
Leichtigkeitsrennen im Orbit
Dies ist meiner Meinung nach die beste Antwort. Tatsächlich können Sie das Zeichen '8' auch an Position 0x2440 sehen, zumindest auf meiner Windows 10-Box in der Datei c: \ windows \ system32 \ c_1252.nls ( unendlich ist 0x221E, und die Datei enthält eine Kopfzeile, die den Versatz erklärt). . Alle Codepage-Codierungen haben eine entsprechende .nls-Datei. Standardmäßig verwendet die Konsole die 1252-Codepage (Windows 1252). Beachten Sie, dass diese Zuordnungen nicht beibehalten werden. Überprüfen Sie dies: blogs.msdn.microsoft.com/shawnste/2007/09/24/…
Simon Mourier
35

Hinweis: Der implizite .ToString()Methodenaufruf beim SchreibenDouble.PositiveInfinity in die Konsole ist für dieses Verhalten verantwortlich.

Berufung Console.WriteLine(Double.PositiveInfinity.ToString(new CultureInfo("en-Us")));

ergibt die Zeichenfolge "Infinity"

während Console.WriteLine(Double.PositiveInfinity.ToString(new CultureInfo("fr-Fr"))); ergibt "+ Infini".

Bearbeiten: Wie andere in den Commets betont haben, können sie meine Ergebnisse nicht vollständig bestätigen. Wenn ich das auf einer anderen Maschine teste, bekomme ich den Charakter für beide Anrufe.

Ausgabe für alle Kulturen dank vtortola in den Kommentaren.


Ich habe eine (wahrscheinliche) Antwort gefunden:

Mit Console.OutputEncoding = Encoding.Unicode;I kann ich das Verhalten, das Sie für mehrere Kulturen erleben, nachbilden, z. B. "ru", "ru-RU", um die Ausgabe zu erzeugen 8.

Søren D. Ptæus
quelle
1
Aus Interesse habe ich Ihre Beispiele ausprobiert und beide drucken 8
TheLethalCoder
1
@ TheLethalCoder Ich bekomme Infinityin beiden. Welche Kultur hat Ihre App? Überprüfen Sie Thread.CurrentThread.CurrentCultureund Thread.CurrentThread.CurrentUICulture.
Vtortola
8
@ Søren D. Ptæus tbh Ich kann keine Kultur sehen, die ein 8 dotnetfiddle.net/QYhXMu
vtortola
1
Sie haben Recht mit dem Impliziten .ToString(). Am Ende ToString()wird das .PositiveInfinitySymbolder relevanten zurückgegeben NumberFormatInfo. Diese scheinen von der Laufzeitversion und / oder der Windows-Version (oder einem anderen Betriebssystem) abzuhängen. In den alten Tagen CultureInfo.GetCultureInfo("en-US").NumberFormat.PositiveInfinitySymbolwäre das gleich "Infinity", aber mit neueren Versionen der Laufzeit und des Betriebssystems ist es "∞"stattdessen. Ich habe gerade in einem Kommentar zu Hans Passants Antwort in diesem Thread danach gefragt.
Jeppe Stig Nielsen
16

Repro-Code:

using System;
using System.Text;

class Program {
    static void Main(string[] args) {
        var infinity = "\u221e";
        Console.OutputEncoding = Encoding.GetEncoding(1252);
        Console.WriteLine(infinity);
        Console.ReadLine();
    }
}

Codepage 1252 ist ein ziemlich häufiger Unfall in England, da es dort die Standard-Windows-Codepage ist. Wie für Westeuropa und Amerika. Viele Gründe, die Standardeigenschaft Console.OutputEncoding programmgesteuert zu ändern, viele Textdateien werden 1252 codiert. Oder über die Befehlszeile durch Eingabechcp 1252 (chcp == change code page) ein, bevor Sie das Programm starten.

Wie Sie dem von 1252 unterstützten Zeichensatz entnehmen können, ist das Unendlichkeitssymbol nicht verfügbar. Die Kodierung muss also einen Ersatz finden. Dies ist häufig die ?Glyphe für nicht unterstützte Unicode-Codepunkte, der Encoding.EncoderFallback-Eigenschaftswert für 8-Bit-Codierungen. Für 1252 und die alten MS-Dos 850- und 858-Codepages entschied sich der Microsoft-Programmierer jedoch für8 . Lustiger Kerl.

Die Glyphe wird in der üblichen Codepage für Konsolen-Apps auf einem westlichen Computer unterstützt. Das ist 437, entspricht dem alten IBM-Zeichensatz . Aufgrund dieser Art von Codierungskatastrophen wurde Unicode erfunden. Leider zu spät, um Konsolen-Apps zu retten, viel zu viel Code, der auf der Standard-MS-Dos-Codepage basiert.

Die Konvertierung von Double.PositiveInfinity in "∞" ist spezifisch für Win10. In früheren Windows-Versionen war es "Infinity". Diese Formate können normalerweise über Systemsteuerung> Sprache> Datums-, Uhrzeit- oder Zahlenformate ändern> Schaltfläche Zusätzliche Einstellungen geändert werden. Die Auswahl des Unendlichkeitssymbols ist jedoch nicht im Dialogfeld enthalten. Auch nicht von der Registrierung abgedeckt (HKCU \ Control Panel \ International), eher ein großes Versehen. Es ist LOCALE_SPOSINFINITY im nativen Winapi. In einem .NET-Programm können Sie es programmgesteuert überschreiben, indem Sie CultureInfo klonen und seine NumberFormatInfo.PositiveInfinitySymbol-Eigenschaft ändern. So was:

using System;
using System.Text;
using System.Threading;
using System.Globalization;

class Program {
    static void Main(string[] args) {
        Console.OutputEncoding = Encoding.GetEncoding(1252);
        var ci = (CultureInfo)Thread.CurrentThread.CurrentCulture.Clone();
        ci.NumberFormat.NegativeInfinitySymbol = "-Infinity";
        ci.NumberFormat.PositiveInfinitySymbol = "And beyond";
        Thread.CurrentThread.CurrentCulture = ci;
        Console.WriteLine(1 / 0.0);
        Console.ReadLine();
    }
}
Hans Passant
quelle
Mit Ihrem Code konnte ich bestätigen, dass WinXP die Codepage 437 verwendet, die in Windows 10 jetzt ýanstelle von gedruckt wird . Es hat mir auch gezeigt, dass die Verwendung von Nicht-Raster-Schriftarten das Problem vermeidet.
Mark Hurd
Ist es die Version der .NET - Laufzeit oder die Version von Windows (oder was auch immer O) oder einer Kombination, die feststellt , ob CultureInfo.GetCultureInfo("en-US").NumberFormat.PositiveInfinitySymbolgibt "Infinity"oder "∞"(oder etwas anderes)? Sie sagen oben, dass es spezifisch für Windows 10 ist, und ich stimme zu, dass es irgendwann geändert wurde. Wenn ich jedoch eine Anwendung unter Windows 8 mit "derselben" Version von .NET Framework ausführe , erhalte ich dann ein anderes Ergebnis als unter Windows 10?
Jeppe Stig Nielsen
Dieses Problem beginnt mit Windows und macht dann in .NET eine Eigenart sichtbar. Win8 bevorzugt immer noch "Infinity"
Hans Passant
1
Bestätigt! Ich habe mich gerade bei einem Windows Server 2012 R2-Computer angemeldet (entspricht in etwa Windows 8.1) und weiß, dass er über das neueste .NET Framework und die neueste Windows PowerShell verfügt. In PowerShell $PSVersionTablezeigt sich , dass die PS-Version etwas mit 5.1 ist. Diese PowerShell zielt auf die .NET Framework (CLR) -Version 4 ab. * Ich weiß, dass sie auf diesem Computer neu ist. Noch [cultureinfo]::GetCultureInfo("en-US").NumberFormat.PositiveInfinitySymbolvon Windows gibt PowerShell Infinitynicht (aktuelle Kultur ist en-US). Fazit: Die Windows-Version entscheidet, nicht die .NET-Version.
Jeppe Stig Nielsen
0

"8" für unendlich wird in der Konsole angezeigt, wenn .Net 4 und höher ausgeführt wird, andernfalls wird in früheren Versionen "unendlich" angezeigt.

Verwenden von Console.OutputEncoding = Encoding.Unicode; In .NET 4 und höher wird die Unendlichkeit als ∞ angezeigt, in früheren Versionen wird jedoch eine IOException ausgelöst.

HINWEIS: Ich verwende Visual Studio 2015 Community Edition unter Windows 10 64-Bit

Dave Russell
quelle