Dlaczego nieskończoność jest drukowana jako „8” na konsoli systemu Windows 10?


146

I testował co wrócił z podziałem tym zer tj 0/1, 1/0i 0/0. Do tego użyłem czegoś podobnego do następującego:

Console.WriteLine(1d / 0d);

Jednak ten kod 8nie wypisuje żadnych Infinitylub innych stałych łańcuchowych, takich jak PositiveInfinity.

Dla kompletności wszystkie poniższe wydruki 8:

Console.WriteLine(1d / 0d);

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

Console.WriteLine(Double.PositiveInfinity);

I Console.WriteLine(Double.NegativeInfinity);wydruki -8.

Dlaczego ta nieskończoność drukuje 8?


Dla tych z was, którzy wydają się myśleć, że jest to symbol nieskończoności, a nie ósemka, następujący program:

Console.WriteLine(1d / 0d);

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

Console.WriteLine(Double.PositiveInfinity);

Console.WriteLine(8);

Wyjścia:

Wyjście lnifinity


69
Widzisz, to znak nieskończoności. wystarczy obrócić o 90 stopni, aby to zobaczyć. 8
Mohit Shrivastava,

23
Czy na pewno jest to rzeczywisty 8, a nie jakiś dziwny znak Unicode oznaczający nieskończoność, obrócony o 90 stopni? Może się to zmienić w zależności od ustawień regionalnych. Wypróbowałem to na dotnetfiddle.net i drukuje Infinity.
Kroltan

4
@TheLethalCoder Zrób to, co zasugerował Sinatr, lub wydrukuj wynik Double.PositiveInfinity.ToString()[0] == '8'. Istnieje kilka egzotycznych znaków, które w niektórych czcionkach wyglądają bardzo podobnie do innych. Na jaki język jest skonfigurowany Twój komputer?
Kroltan

15
Wydaje się, że jest to problem z systemem Windows 10. W Windows 8.1 miałem symbol nieskończoności. Uaktualniony kilka dni temu do Windows 10, a teraz mam 8też (język niemiecki).
René Vogt

13
Szybkim sprawdzeniem byłoby sprawdzenie, co się stanieConsole.Write("∞");
Jon Hanna

Odpowiedzi:


110

Zapewniamy, że wartość zmiennoprzecinkowa ma wartość, +Infinityjeśli licznik dzielenia zmiennoprzecinkowego przez zero jest dodatni, -Infinityjeśli licznik dzielenia zmiennoprzecinkowego przez zero jest ujemny i NaNjeśli zarówno licznik, jak i mianownik dzielenia zmiennoprzecinkowego są równe zero. To jest w specyfikacji zmiennoprzecinkowej IEEE754 , której używa C #.

W twoim przypadku konsola konwertuje symbol nieskończoności (który czasami jest reprezentowany typograficznie jako pozioma 8 - ∞) na pionową 8.


13
@TheLethalCoder Zdjęcie nie obala tej odpowiedzi, ponieważ jest to zdjęcie twojej konsoli
Rob

9
@Rob Źle odczytałem odpowiedź, ale to nasuwa pytania, dlaczego zamienia ją na 8? I dlaczego niektóre skrzypce / konsole drukują literał ciągu
TheLethalCoder

1
Wydaje się, że tak jest w przypadku używania debugera. Widzę symbol nieskończoności (tj. Poziomą 8), czy jest jakiś powód, dla którego moja konsola zmieniłaby się na 8, podczas gdy wszyscy inni wydają się używać Infinitylub podobnego, nawet jeśli używam kodu z odpowiedzi przez Soren, określając kulturę
TheLethalCoder

4
Nazywa się to „lemniscate”. Ma wartość Unicode: ∞
BlueRaja - Danny Pflughoeft

14
To prawdopodobnie wyjaśnia, dlaczego Buzz Lightyear mówi „Za ósemkę i nie tylko!” kiedy gram w Toy Story na moim komputerze. ;)
DeanOC

70

Przy określonych ustawieniach (np. Kombinacja kultur, kodowanie wyjściowe itp.) .NET wyświetli znak nieskończoności Unicode ∞ (∞ / & # 8734;). Emulator konsoli / terminala systemu Windows 10 (ponownie przy pewnych ustawieniach - patrz zrzut ekranu poniżej) wyświetli ten znak Unicode jako 8.

Na przykład w systemie Windows 10 z poniższymi ustawieniami (zwróć uwagę na stronę kodową) po prostu wklejając ∞ do konsoli, wyświetla się jako 8.

Ustawienie do reprodukcji

EDYTOWAĆ

Podziękowania dla komentarza Chrisa : Wygląda na to, że czcionka wyjściowa w połączeniu ze stroną kodową jest odpowiedzialna za problem ∞ => 8 na konsoli. Podobnie jak on, otrzymuję poprawne wyświetlanie ∞ we wszystkich czcionkach TrueType, które wypróbowałem i widzę tylko 8, gdy wybrana jest czcionka rastrowa.

ustawienia czcionek


1
Mój faktycznie pokazuje znak nieskończoności na boku zamiast „8” po wklejeniu w konsoli, chociaż używam „437 (OEM - Stany Zjednoczone)”
Derek 朕 會 功夫

3
Chociaż odpowiedź jest prawidłowa, że ​​pewne ustawienia mogą powodować ten problem z wyświetlaniem, druga połowa jest nieprawidłowa. Moje opcje wyglądają obecnie dokładnie tak samo jak Twoje powyżej i otrzymuję poprawne ∞ zamiast 8. Mogę tylko wyświetlić 8, jeśli przejdę do strony czcionek i wybiorę „czcionki rastrowe” z listy dostępnych czcionek. Consolas, Courier New i inni wydają się to dobrze prezentować ...
Chris,

Zdecydowanie jest to kombinacja tych dwóch czynników, ponieważ ustawienie czcionki na Raster, gdy strona kodowa 437 nadal wyświetla symbol poprawnie. Tylko wtedy, gdy spełnione są oba warunki, wydaje się, że tak się dzieje (przynajmniej dla mnie).
Moshe Katz

39

8Symbol pojawia się, gdy system Windows konwertuje Unicode do kodowania znaków dziedzictwo. Ponieważ w dotychczasowym kodowaniu nie ma symbolu nieskończoności , domyślnie stosuje się „najlepsze dopasowanie” do tego symbolu , którym w tym przypadku jest liczba 8. Zobacz przykład kodowania Microsoft „windows-1252” . Wygląda na to, że system Windows 10 nadal domyślnie używa starszych kodowań znaków w konsoli (patrz „Strony kodowe” ).


11
Zastanawiam się, dlaczego „8” jest uważane za dobre dopasowanie, skoro semantycznie jest tak podatne na wywołanie zamieszania? Inne znaki na stronie kodowej 437 wydają się lepiej pasować, na przykład znak stopnia lub znak promila (% z dwoma „o” pod ukośnikiem). Żaden z nich nie byłby tak dobry jak rzeczywisty znak nieskończoności, ale wydawałyby się mniej podatne na wprowadzanie zamieszania.
supercat

„Wygląda na to, że system Windows 10 nadal domyślnie używa starszych kodowań znaków w konsoli” Nie, mój plik cmd.exe w systemie Windows 10 ma wyłączone kodowanie starszego typu.
Wyścigi lekkości na orbicie,

To najlepsza odpowiedź IMHO. W rzeczywistości możesz również zobaczyć znak `` 8 '' w pozycji 0x2440 przynajmniej na moim pudełku z systemem Windows 10 w pliku c: \ windows \ system32 \ c_1252.nls ( nieskończoność to 0x221E, a plik ma nagłówek wyjaśniający przesunięcie) . Wszystkie kodowania stron kodowych mają odpowiedni plik .nls. Domyślnie konsola używa strony kodowej 1252 (Windows 1252). Pamiętaj, że te mapowania nie zostaną zachowane, sprawdź to: blogs.msdn.microsoft.com/shawnste/2007/09/24/…
Simon Mourier

35

Uwaga: za to zachowanie odpowiada niejawne .ToString()wywołanie metody podczas pisania Double.PositiveInfinitydo konsoli.

Powołanie Console.WriteLine(Double.PositiveInfinity.ToString(new CultureInfo("en-Us")));

daje w wyniku ciąg „Infinity”

podczas gdy Console.WriteLine(Double.PositiveInfinity.ToString(new CultureInfo("fr-Fr"))); daje w wyniku „+ Infini”.

Edycja: Jak zauważyli inni w komunikatach, nie mogą całkowicie potwierdzić moich wyników. Testując to na innym komputerze, otrzymuję postać dla obu połączeń.

Wyjście dla wszystkich kultur , dzięki vtortola w komentarzach.


Znalazłem (prawdopodobną) odpowiedź:

Używając Console.OutputEncoding = Encoding.Unicode;I, mogę odtworzyć zachowanie, którego doświadczasz w kilku kulturach, np. „Ru”, „ru-RU” dają wynik 8.


1
Z zainteresowania wypróbowałem twoje przykłady i oba wypisują 8
TheLethalCoder

1
@TheLethalCoder Mam Infinityw obu. W jakiej kulturze działa Twoja aplikacja? Sprawdź Thread.CurrentThread.CurrentCulturei Thread.CurrentThread.CurrentUICulture.
vtortola

8
@ Søren D. Ptæus tbh Nie widzę żadnej kultury generującej 8 dotnetfiddle.net/QYhXMu
vtortola

1
Masz rację co do ukrytych .ToString(). W końcu ToString()zwróci .PositiveInfinitySymbolodpowiednie NumberFormatInfo. Wydaje się, że zależą one od wersji środowiska wykonawczego i / lub wersji systemu Windows (lub innego systemu operacyjnego). W dawnych czasach CultureInfo.GetCultureInfo("en-US").NumberFormat.PositiveInfinitySymbolbyłby równy "Infinity", ale w nowszych wersjach środowiska wykonawczego i systemu operacyjnego tak jest "∞". Właśnie o to zapytałem w komentarzu do odpowiedzi Hansa Passanta w tym wątku.
Jeppe Stig Nielsen

16

Kod repro:

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();
    }
}

Strona kodowa 1252 jest dość częstym przypadkiem w Anglii, ponieważ jest tam domyślną stroną kodową systemu Windows. Tak jak w przypadku Europy Zachodniej i obu Ameryk. Jest wiele powodów, dla których warto programowo zmienić domyślną właściwość Console.OutputEncoding, wiele plików tekstowych zostanie zakodowanych w 1252. Lub z wiersza poleceń, wpisując chcp 1252(chcp == zmień stronę kodową) przed uruchomieniem programu.

Jak widać z zestawu znaków obsługiwanego przez 1252, symbol nieskończoności nie jest dostępny. Więc kodowanie musi wymyślić substytut. Często jest to ?glif dla nieobsługiwanych punktów kodowych Unicode, wartość właściwości Encoding.EncoderFallback dla kodowania 8-bitowego. Ale dla 1252 i starszych stron kodowych MS-Dos 850 i 858 zdecydował się programista Microsoft 8. Zabawny facet.

Glif jest obsługiwany na zwykłej stronie kodowej aplikacji konsolowych na maszynie zachodniej. Który wynosi 437, pasuje do starszego zestawu znaków IBM . Mając tego rodzaju katastrofy kodowania, wymyślono Unicode. Niestety za późno na ratowanie aplikacji konsolowych, za dużo kodu związanego z domyślną stroną kodową MS-Dos.

Konwersja Double.PositiveInfinity na „∞” jest specyficzna dla Win10. W poprzednich wersjach systemu Windows było to „Infinity”. Te rodzaje formatów można normalnie modyfikować za pomocą opcji Panel sterowania> Język> Zmień format daty, godziny lub liczb> przycisk Ustawienia dodatkowe, ale wybór symbolu nieskończoności nie jest uwzględniany w oknie dialogowym. Również nie objęty rejestrem (HKCU \ Control Panel \ International), raczej duże niedopatrzenie. To jest LOCALE_SPOSINFINITY w rodzimym winapi. W programie .NET można nadpisać to programowo, klonując CultureInfo i zmieniając jego właściwość NumberFormatInfo.PositiveInfinitySymbol. Lubię to:

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();
    }
}

Twój kod pozwolił mi potwierdzić, że WinXP używa strony kodowej 437, która w systemie Windows 10 jest teraz drukowana ýzamiast . Pokazał mi również, że użycie czcionek innych niż rastrowe pozwala uniknąć problemu.
Mark Hurd,

Czy jest to wersja środowiska uruchomieniowego .NET, czy wersja systemu Windows (lub innego systemu operacyjnego), czy też kombinacja, która określa, czy CultureInfo.GetCultureInfo("en-US").NumberFormat.PositiveInfinitySymboldaje "Infinity"lub "∞"(lub coś innego)? Powiedziałeś powyżej, że jest specyficzny dla systemu Windows 10 i zgadzam się, że został kiedyś zmieniony. Jeśli jednak uruchomię aplikację w systemie Windows 8 z „tą samą” wersją programu .NET Framework , czy uzyskam inny wynik niż w systemie Windows 10?
Jeppe Stig Nielsen

Ten problem zaczyna się w systemie Windows, a następnie ujawnia dziwactwo w .NET. Win8 nadal faworyzuje "Infinity"
Hans Passant

1
Potwierdzony! Właśnie zalogowałem się na komputerze z systemem Windows Server 2012 R2 (odpowiada z grubsza Windows 8.1) i wiem, że ma najnowszy .NET Framework, a także najnowszy Windows PowerShell. W PowerShell $PSVersionTableujawnia, że ​​wersja PS to coś z 5.1. Ten program PowerShell jest przeznaczony dla .NET Framework (CLR) w wersji 4. *, o której wiem, że jest nowością na tym komputerze. Jeszcze [cultureinfo]::GetCultureInfo("en-US").NumberFormat.PositiveInfinitySymbolz Windows PowerShell daje Infinity, nie (obecna kultura jest en-US). Wniosek: decyduje wersja systemu Windows, a nie wersja .NET.
Jeppe Stig Nielsen

0

„8” dla nieskończoności jest wyświetlane w konsoli podczas uruchamiania .Net 4 i nowszych, w przeciwnym razie poprzednie wersje wyświetlają „Infinity”.

Using Console.OutputEncoding = Encoding.Unicode; w .Net 4 i nowszych spowoduje wyświetlenie nieskończoności jako ∞, ale w poprzednich wersjach zgłosi wyjątek IOException.

UWAGA: używam programu Visual Studio 2015 Community Edition w systemie Windows 10 w wersji 64-bitowej

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.