Mengapa infinity dicetak sebagai "8" di konsol Windows 10?

146

Saya menguji apa yang dikembalikan dari divisi termasuk nol yaitu 0/1, 1/0dan 0/0. Untuk ini saya menggunakan sesuatu yang mirip dengan yang berikut:

Console.WriteLine(1d / 0d);

Namun kode ini 8tidak mencetak Infinityatau string konstan lainnya suka PositiveInfinity.

Untuk melengkapi semua cetakan berikut 8:

Console.WriteLine(1d / 0d);

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

Console.WriteLine(Double.PositiveInfinity);

Dan Console.WriteLine(Double.NegativeInfinity);cetakan -8.

Mengapa infinity ini mencetak 8?


Bagi Anda yang tampaknya berpikir ini adalah simbol infinity bukan delapan program berikut:

Console.WriteLine(1d / 0d);

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

Console.WriteLine(Double.PositiveInfinity);

Console.WriteLine(8);

Output:

Keluaran inifinity

TheLethalCoder
sumber
69
Anda lihat adalah tanda ketidakterbatasan. balik saja 90 derajat untuk melihatnya 8
Mohit Shrivastava
23
Apakah Anda yakin itu adalah 8karakter Unicode yang sebenarnya , bukan yang aneh untuk infinity, diputar 90 derajat? Ini bisa berubah berdasarkan lokasi Anda. Saya mencobanya di dotnetfiddle.net dan hasilnya tercetak Infinity.
Kroltan
4
@TheLethalCoder Tolong lakukan apa yang disarankan Sinatr, atau cetak hasilnya Double.PositiveInfinity.ToString()[0] == '8'. Ada beberapa karakter eksotis yang terlihat sangat mirip dengan yang lain di beberapa font. Selain itu, bahasa apa yang dikonfigurasikan komputer Anda?
Kroltan
15
Ini tampaknya menjadi masalah Windows 10. Di Windows 8.1 saya memiliki simbol infinity. Diupgrade beberapa hari yang lalu ke Windows 10 dan sekarang saya juga punya 8(bahasa Jerman).
René Vogt
13
Pemeriksaan cepat adalah untuk melihat apa yang terjadi Console.Write("∞");
Jon Hanna

Jawaban:

110

Yakinlah bahwa nilai floating point adalah +Infinityjika pembilang dari divisi floating point dengan nol adalah positif, -Infinityjika pembilang dari pembagian floating point dengan nol adalah negatif, dan NaNjika pembilang dan penyebut dari divisi floating point keduanya nol. Itu dalam spesifikasi floating point IEEE754 , yang digunakan oleh C #.

Dalam kasus Anda, the konsol sedang mengubah simbol infinity (yang kadang-kadang digambarkan secara tipografis sebagai horizontal 8 - ∞) menjadi vertikal 8.

Batsyeba
sumber
13
@TheLethalCoder Gambar tidak membuktikan jawaban ini, karena ini adalah gambar konsol Anda
Rob
9
@Rob Saya salah membaca jawabannya, namun itu menimbulkan pertanyaan, mengapa ia mengubahnya menjadi 8? Dan mengapa beberapa biola / konsol mencetak string literal
TheLethalCoder
1
Ini tampaknya menjadi kasus menggunakan debugger Saya melihat simbol infinity (yaitu horisontal 8), apakah ada alasan konsol saya akan dikonversi ke 8 sementara semua orang tampaknya menggunakan Infinityatau serupa bahkan jika saya menggunakan kode dari jawaban oleh Soren dengan menentukan budaya
TheLethalCoder
4
Ini disebut "lemniscate". Ini memiliki nilai unicode: ∞
BlueRaja - Danny Pflughoeft
14
Ini mungkin menjelaskan mengapa Buzz Lightyear mengatakan "To Eight And Beyond!" ketika saya memainkan Toy Story di PC saya. ;)
DeanOC
70

Diberikan pengaturan tertentu (yaitu kombinasi budaya, pengkodean keluaran, dll.). NET akan menampilkan karakter infode Unicode ∞ (∞ / & # 8734;). Emulator konsol / terminal Windows 10 akan (sekali lagi diberikan pengaturan tertentu - lihat tangkapan layar di bawah) menampilkan karakter Unicode ini sebagai 8.

Sebagai contoh, pada Windows 10, dengan pengaturan di bawah ini (perhatikan halaman kode) hanya menempelkan ∞ ke dalam konsol yang menunjukkan 8.

Pengaturan untuk mereproduksi

EDIT

Dengan terima kasih atas komentar dari Chris : Tampaknya font output dalam kombinasi dengan halaman kode bertanggung jawab atas masalah ∞ => 8 pada konsol. Seperti dia, saya mendapatkan tampilan yang benar dari ∞ di semua font TrueType yang telah saya coba dan hanya melihat 8 ketika font raster dipilih.

pengaturan font

Tolanj
sumber
1
Milik saya benar-benar menunjukkan tanda infinity di sisinya alih-alih "8" ketika disisipkan di konsol, meskipun saya menggunakan "437 (OEM - Amerika Serikat)"
Derek 朕 會 功夫
3
Meskipun jawabannya benar bahwa pengaturan tertentu dapat menyebabkan masalah tampilan ini, bagian kedua tidak benar. Opsi saya saat ini terlihat persis sama dengan milik Anda di atas dan saya mendapatkan yang benar ∞ daripada yang 8. Saya hanya bisa membuatnya untuk menampilkan 8 jika saya pergi ke halaman font dan memilih "font raster" dari daftar font yang tersedia. Consolas, Courier New, dan yang lainnya semuanya sepertinya menampilkannya dengan baik ...
Chris
Ini pasti kombinasi dari dua faktor, karena pengaturan font ke Raster ketika codepage adalah 437 masih menunjukkan simbol dengan benar. Hanya jika kedua kondisi terpenuhi, hal ini tampaknya terjadi (setidaknya untuk saya).
Moshe Katz
39

The 8simbol terjadi ketika Windows mengkonversi Unicode ke pengkodean karakter warisan. Karena tidak ada simbol tak terhingga dalam penyandian sebelumnya, secara default ia menggunakan "paling cocok" untuk simbol itu , yang dalam hal ini adalah angka 8. Lihat contoh untuk pengkodean "windows-1252" Microsoft . Rupanya, Windows 10 masih menggunakan penyandian karakter lama secara default di konsol (lihat "Halaman Kode" ).

Peter O.
sumber
11
Saya bertanya-tanya mengapa "8" dianggap cocok, ketika secara semantik cenderung menimbulkan kebingungan? Karakter lain dalam kode halaman 437 akan tampak lebih cocok, seperti tanda derajat atau tanda per-mille (% dengan dua o di bawah garis miring). Tak satu pun dari mereka akan sebagus pertanda tak terhingga yang sebenarnya, tetapi mereka tampaknya kurang cenderung menyebabkan kebingungan.
supercat
"Rupanya, Windows 10 masih menggunakan pengkodean karakter warisan secara default di konsol" Tidak, Windows 10 cmd.exe saya telah menonaktifkan pengodean warisan.
Lightness Races in Orbit
Ini adalah jawaban IMHO terbaik. Sebenarnya, Anda juga dapat melihat karakter '8' di posisi 0x2440 setidaknya pada kotak Windows 10 saya di file c: \ windows \ system32 \ c_1252.nls ( infinity 0x221E, dan file tersebut memiliki beberapa header yang menjelaskan offset) . Semua pengkodean codepage memiliki file .nls yang sesuai. Secara default, konsol menggunakan halaman kode 1252 (Windows 1252). Perhatikan pemetaan ini tidak akan dipertahankan, periksa ini: blogs.msdn.microsoft.com/shawnste/2007/09/24/…
Simon Mourier
35

Catatan: .ToString()Metode panggilan implisit saat menulis Double.PositiveInfinityke konsol bertanggung jawab atas perilaku ini.

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

menghasilkan string "Infinity"

sementara Console.WriteLine(Double.PositiveInfinity.ToString(new CultureInfo("fr-Fr"))); menghasilkan "+ Infini".

Sunting: Seperti yang orang lain tunjukkan di commets, mereka tidak dapat sepenuhnya mengkonfirmasi hasil saya. Menguji ini pada mesin yang berbeda, saya mendapatkan karakter untuk kedua panggilan.

Keluaran untuk semua budaya , terima kasih kepada vtortola di komentar.


Saya menemukan jawaban (kemungkinan):

Menggunakan Console.OutputEncoding = Encoding.Unicode;I dapat menciptakan kembali perilaku yang Anda alami untuk beberapa budaya, misalnya "ru", "ru-RU" menghasilkan output 8.

Søren D. Ptæus
sumber
1
Karena ketertarikan saya mencoba contoh Anda dan mereka berdua mencetak 8
TheLethalCoder
1
@TheLethalCoder saya dapatkan Infinitydi keduanya. Budaya mana yang dijalankan aplikasi Anda? Periksa Thread.CurrentThread.CurrentCulturedan Thread.CurrentThread.CurrentUICulture.
vtortola
8
@ Søren D. Ptæus tbh Saya tidak bisa melihat budaya yang menghasilkan 8 dotnetfiddle.net/QYhXMu
vtortola
1
Anda benar tentang yang tersirat .ToString(). Pada akhirnya, ToString()akan mengembalikan .PositiveInfinitySymbolyang relevanNumberFormatInfo . Ini tampaknya tergantung pada versi runtime dan / atau versi Windows (atau OS apa pun). Di masa lalu, CultureInfo.GetCultureInfo("en-US").NumberFormat.PositiveInfinitySymbolakan sama dengan "Infinity", tetapi dengan versi yang lebih baru dari runtime dan sistem operasi "∞". Saya hanya bertanya tentang hal itu dalam komentar atas jawaban Hans Passant di utas ini.
Jeppe Stig Nielsen
16

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

Halaman kode 1252 adalah kecelakaan yang cukup umum di Inggris karena ini adalah halaman kode Windows default di sana. Seperti untuk Eropa Barat dan Amerika. Banyak alasan untuk mengubah properti Console.OutputEncoding default secara terprogram, banyak file teks akan dikodekan pada 1252. Atau dari baris perintah dengan mengetikchcp 1252 (chcp == halaman kode ganti) sebelum memulai program.

Seperti yang dapat Anda ketahui dari rangkaian karakter yang didukung oleh 1252, simbol Infinity tidak tersedia. Jadi Pengkodean harus datang dengan pengganti. Itu sering merupakan ?mesin terbang untuk titik kode Unicode yang tidak didukung, nilai properti Encoding.EncoderFallback untuk penyandian 8-bit. Tetapi untuk 1252, dan warisan MS-Dos 850 dan 858 halaman kode, programmer Microsoft memutuskan untuk melakukannya8 . Orang yang lucu.

Mesin terbang itu adalah didukung dalam halaman kode biasa untuk konsol aplikasi pada mesin Barat. Yaitu 437, cocok dengan rangkaian karakter IBM sebelumnya . Memiliki jenis bencana pengkodean inilah sebabnya Unicode ditemukan. Sayangnya terlambat untuk menyelamatkan aplikasi konsol, terlalu banyak kode di sekitar yang bergantung pada halaman kode MS-Dos default.

Memiliki Double.PositiveInfinity dikonversi ke "∞" khusus untuk Win10. Dulu "Infinity" di versi Windows sebelumnya. Format semacam ini biasanya dapat dimodifikasi dengan Control Panel> Bahasa> Ubah format tanggal, waktu, atau angka> tombol Pengaturan Tambahan tetapi pemilihan simbol infinity tidak termasuk dalam dialog. Juga tidak tercakup oleh registri (HKCU \ Control Panel \ International), lebih merupakan pengawasan besar. Ini adalah LOCALE_SPOSINFINITY di winapi asli. Dalam program .NET Anda dapat menimpanya secara terprogram dengan mengkloning CultureInfo dan mengubah properti NumberFormatInfo.PositiveInfinitySymbol. Seperti ini:

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
sumber
Kode Anda memungkinkan saya untuk mengonfirmasi WinXP menggunakan kode halaman 437, yang, pada Windows 10, sekarang dicetak ýsebagai ganti . Ini juga menunjukkan kepada saya bahwa menggunakan font non-raster menghindari masalah.
Mark Hurd
Apakah versi runtime .NET, atau versi Windows (atau OS apa pun), atau kombinasi, yang menentukan apakah CultureInfo.GetCultureInfo("en-US").NumberFormat.PositiveInfinitySymbolmemberi "Infinity"atau "∞"(atau sesuatu yang lain)? Anda mengatakan di atas bahwa ini khusus untuk Windows 10, dan saya setuju itu diubah pada suatu waktu. Tetapi jika saya menjalankan aplikasi pada Windows 8 dengan versi .NET Framework yang sama , akankah saya mendapatkan hasil yang berbeda dibandingkan dengan Windows 10?
Jeppe Stig Nielsen
Masalah ini dimulai dengan Windows, kemudian memperlihatkan kekhasan dalam .NET. Win8 masih menyukai "Infinity"
Hans Passant
1
Dikonfirmasi! Saya baru saja masuk ke mesin Windows Server 2012 R2 (kira-kira sesuai dengan Windows 8.1), dan saya tahu ia memiliki .NET Framework terbaru, dan juga memiliki Windows PowerShell terbaru. Di PowerShell, $PSVersionTablemengungkapkan versi PS adalah sesuatu dengan 5.1. PowerShell itu menargetkan .NET Framework (CLR) versi 4. * yang saya tahu baru di mesin itu. Masih [cultureinfo]::GetCultureInfo("en-US").NumberFormat.PositiveInfinitySymboldari Windows PowerShell memberi Infinity, bukan (budaya saat ini en-US). Kesimpulan: Versi Windows memutuskan, bukan versi .NET.
Jeppe Stig Nielsen
0

"8" untuk infinity ditampilkan di konsol saat menjalankan .Net 4 dan di atasnya, jika tidak, versi sebelumnya menampilkan "Infinity".

Menggunakan Console.OutputEncoding = Encoding.Unicode; di .Net 4 dan di atasnya akan mendapatkan infinity untuk ditampilkan sebagai ∞, tetapi melempar IOException di versi sebelumnya.

CATATAN: Saya menjalankan Visual Studio 2015 Community Edition pada Windows 10 64-bit

Dave Russell
sumber