Почему бесконечность печатается как «8» в консоли Windows 10?

146

Я испытывал то , что было возвращено от деления , включая нули т 0/1, 1/0и 0/0. Для этого я использовал что-то похожее на следующее:

Console.WriteLine(1d / 0d);

Однако этот код 8не печатает, Infinityили какая-то другая строковая константа, как PositiveInfinity.

Для полноты всего ниже напечатайте 8:

Console.WriteLine(1d / 0d);

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

Console.WriteLine(Double.PositiveInfinity);

И Console.WriteLine(Double.NegativeInfinity);печатает -8.

Почему эта бесконечность печатает 8?


Для тех из вас, кто, кажется, думает, что это символ бесконечности, а не восьмерка, следующая программа:

Console.WriteLine(1d / 0d);

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

Console.WriteLine(Double.PositiveInfinity);

Console.WriteLine(8);

Выходы:

Выход Inifinity

TheLethalCoder
источник
69
Вы видите, это знак бесконечности. просто переверните его на 90 градусов, чтобы увидеть его 8
Мохит Шривастава
23
Вы уверены, что это настоящий 8, а не какой-то странный Unicode-символ для бесконечности, повернутый на 90 градусов? Это может измениться в зависимости от вашей локали. Я попробовал это на dotnetfiddle.net, и он печатает Infinity.
Кролтан
4
@TheLethalCoder Пожалуйста, сделайте то, что предложил Синатр, или распечатайте вывод Double.PositiveInfinity.ToString()[0] == '8'. В некоторых шрифтах есть некоторые экзотические символы, которые очень похожи на других. Кроме того, на каком языке настроен ваш компьютер?
Кролтан
15
Кажется, это проблема Windows 10. В Windows 8.1 у меня был символ бесконечности. Обновлен несколько дней назад до Windows 10, и теперь у меня 8тоже есть (немецкий язык).
Рене Фогт
13
Быстрая проверка была бы, чтобы видеть то, что случаетсяConsole.Write("∞");
Джон Ханна

Ответы:

110

Будьте уверены, что значение с плавающей запятой имеет место, +Infinityесли числитель деления с плавающей запятой на ноль является положительным, -Infinityесли числитель деления с плавающей запятой на ноль является отрицательным, и NaNесли числитель и знаменатель деления с плавающей запятой оба равны нулю. Это в спецификации IEEE754 с плавающей точкой , которую использует C #.

В вашем случае консоль преобразует символ бесконечности (который иногда типографски представлен как горизонтальный 8 - ∞) в вертикальный 8.

Вирсавия
источник
13
@TheLethalCoder Изображение не опровергает этот ответ, так как это изображение вашей консоли
Роб
9
@ Роб Я неверно прочитал ответ, однако напрашивается вопрос, почему он конвертирует его в 8? И почему некоторые скрипки / консоли печатают строковый литерал
TheLethalCoder
1
Это похоже на случай использования отладчика. Я вижу символ бесконечности (т.е. горизонтальный 8), есть ли какая-то причина, по которой моя консоль конвертируется в 8, в то время как все остальные, кажется, используют Infinityили похожи, даже если я использую код из ответа Сорен, указав культуру
TheLethalCoder
4
Это называется "лемнискат". Он имеет значение в
юникоде
14
Это, вероятно, объясняет, почему Базз Лайтер говорит "Восемь и дальше!" когда я играю в историю игрушек на моем компьютере. ;)
DeanOC
70

При определенных настройках (т. Е. Комбинации культур, выходной кодировки и т. Д.) .NET будет выводить символ бесконечности Unicode ∞ (∞ / & # 8734;). Эмулятор консоли / терминала Windows 10 (опять же при определенных настройках - см. Скриншот ниже) отображает этот символ Unicode как 8.

Например, в Windows 10 с приведенными ниже настройками (обратите внимание на кодовую страницу) просто вставка ∞ в консоль отображается как 8.

Настройка для воспроизведения

РЕДАКТИРОВАТЬ

Благодаря комментарию Криса : кажется, что выходной шрифт в сочетании с кодовой страницей отвечает за проблему ∞ => 8 на консоли. Как и он, я получаю правильное отображение ∞ во всех шрифтах TrueType, которые я пробовал, и вижу только 8, когда выбраны растровые шрифты.

настройки шрифта

tolanj
источник
1
У меня на самом деле знак бесконечности на боковой стороне вместо «8» при вставке в консоль, хотя я использую «437 (OEM - США)»
Дерек 朕 會 功夫
3
Хотя ответ правильный, что определенные настройки могут вызвать эту проблему, вторая половина неверна. Мои параметры в настоящее время выглядят точно так же, как и выше, и я получаю правильное ∞, а не 8. Я могу заставить его отображать 8, только если я перехожу на страницу шрифтов и выбираю «растровые шрифты» из списка доступных шрифтов. «Консолас», «Курьер Нью» и другие, кажется, прекрасно это показывают ...
Крис
Это определенно комбинация двух факторов, потому что установка шрифта Raster, когда кодовая страница 437, все еще показывает символ правильно. Только если оба условия будут выполнены, это может произойти (по крайней мере, для меня).
Моше Кац
39

8Символ происходит , когда Windows , преобразует Unicode в кодировку символов наследия. Поскольку в устаревшей кодировке нет символа бесконечности, он по умолчанию использует «наилучшую подгонку» к этому символу, в данном случае это номер 8. См. Пример кодировки Microsoft «windows-1252» . По-видимому, Windows 10 по- прежнему использует устаревшие кодировки символов по умолчанию в консоли (см. «Кодовые страницы» ).

Питер О.
источник
11
Интересно, почему «8» считается подходящим, когда оно семантически склонно создавать путаницу? Другие символы в кодовой странице 437 выглядели бы более подходящими, например знак градуса или знак промилле (% с двумя цифрами ниже косой черты). Ни один из них не был бы так же хорош, как действительный знак бесконечности, но они казались бы менее склонными вызывать замешательство.
Суперкат
«Очевидно, что Windows 10 по-прежнему использует устаревшие кодировки символов по умолчанию в консоли» Нет, мой Windows 10 cmd.exe имеет устаревшую кодировку, отключенную из коробки.
Гонки легкости на орбите
Это лучший ответ ИМХО. На самом деле, вы также можете увидеть символ '8' в позиции 0x2440, по крайней мере, в моем окне Windows 10 в файле c: \ windows \ system32 \ c_1252.nls ( бесконечность 0x221E, и у файла есть некоторый заголовок, который объясняет смещение) , Все кодировки кодовых страниц имеют соответствующий файл .nls. По умолчанию консоль использует кодовую страницу 1252 (Windows 1252). Обратите внимание, что эти сопоставления не будут поддерживаться, проверьте это: blogs.msdn.microsoft.com/shawnste/2007/09/24/…
Саймон Мурье
35

Примечание. За это отвечает неявный .ToString()вызов метода при записи Double.PositiveInfinityв консоль.

призвание Console.WriteLine(Double.PositiveInfinity.ToString(new CultureInfo("en-Us")));

Результаты в строке "Бесконечность"

в то время как Console.WriteLine(Double.PositiveInfinity.ToString(new CultureInfo("fr-Fr"))); результаты в "+ Infini".

Изменить: Как отмечалось в комментариях другие, они не могут полностью подтвердить мои результаты. Тестируя это на другой машине, я получаю персонажа для обоих вызовов.

Выход для всех культур , благодаря вторторола в комментариях.


Я нашел (вероятный) ответ:

Использование Console.OutputEncoding = Encoding.Unicode;I может воссоздать поведение, которое вы испытываете для нескольких культур, например, «ru», «ru-RU» выдают результат 8.

Сорен Д. Птюс
источник
1
Из интереса я попробовал ваши примеры, и они оба печатают 8
TheLethalCoder
1
@TheLethalCoder Я получаю Infinityв обоих. Какую культуру использует ваше приложение? Проверьте Thread.CurrentThread.CurrentCultureи Thread.CurrentThread.CurrentUICulture.
Втортола
8
@ Søren D. Ptæus tbh Я не вижу никакой культуры, создающей 8 dotnetfiddle.net/QYhXMu
vtortola
1
Вы правы в отношении неявного .ToString(). В конце концов, ToString()вернется .PositiveInfinitySymbolсоответствующий NumberFormatInfo. Кажется, что они зависят от версии среды выполнения и / или версии Windows (или любой другой ОС). В старые времена CultureInfo.GetCultureInfo("en-US").NumberFormat.PositiveInfinitySymbolбыло бы равным "Infinity", но с более новыми версиями среды выполнения и операционной системы это "∞"вместо. Я просто спросил об этом в комментарии к ответу Ханса Пассанта в этой теме.
Джеппе Стиг Нильсен
16

Код репро:

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

Кодовая страница 1252 - довольно распространенная авария в Англии, поскольку там есть кодовая страница Windows по умолчанию. Как это для Западной Европы и Америки. Множество причин для изменения стандартного свойства Console.OutputEncoding по умолчанию, многие текстовые файлы будут закодированы в 1252. Или из командной строки chcp 1252введите (chcp == изменить кодовую страницу) перед запуском программы.

Как видно из набора символов, поддерживаемого 1252, символ бесконечности недоступен. Таким образом, кодировка должна придумать замену. Это часто ?символ для неподдерживаемых кодовых точек Unicode, значение свойства Encoding.EncoderFallback для 8-битных кодировок. Но для 1252 и устаревших кодовых страниц MS-Dos 850 и 858 программист Microsoft решил 8. Веселый парень.

Глиф это поддерживается в обычной кодовой страницы для консольных приложений на западной машине. То есть 437, соответствует устаревшему набору символов IBM . Именно такие бедствия кодирования - вот почему был изобретен Unicode. К сожалению, слишком поздно, чтобы спасти консольные приложения, слишком много кода вокруг, который полагался на кодовую страницу MS-Dos по умолчанию.

Преобразование Double.PositiveInfinity в «∞» относится к Win10. Раньше это был «Бесконечность» в предыдущих версиях Windows. Такие форматы обычно можно изменить с помощью панели управления> Язык> Изменить формат даты, времени или числа> кнопку Дополнительные настройки, но выбор символа бесконечности не включен в диалог. Также не охватывается реестром (HKCU \ Control Panel \ International), довольно большой недосмотр. Это LOCALE_SPOSINFINITY в родном винапи. В .NET-программе вы можете переопределить ее программно, клонировав CultureInfo и изменив его свойство NumberFormatInfo.PositiveInfinitySymbol. Как это:

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();
    }
}
Ганс Пассант
источник
Ваш код позволил мне подтвердить, что WinXP использует кодовую страницу 437, которая в Windows 10 теперь печатает ýвместо . Это также показало мне, что использование не растровых шрифтов позволяет избежать этой проблемы.
Марк Херд
Является ли версия среды выполнения .NET, или версия Windows (или любой другой ОС) или их комбинацией, которая определяет, CultureInfo.GetCultureInfo("en-US").NumberFormat.PositiveInfinitySymbolдает "Infinity"или "∞"(или что-то еще)? Вы говорите выше, что это специфично для Windows 10, и я согласен, что он был изменен в какой-то момент. Но если я запущу приложение в Windows 8 с «той же» версией .NET Framework , получу ли я другой результат, чем в Windows 10?
Джеппе Стиг Нильсен
Эта проблема начинается с Windows, а затем обнаруживает причуду в .NET. Win8 все еще одобряет "Бесконечность"
Ганс Пассант
1
Подтверждено! Я только что вошел на компьютер с Windows Server 2012 R2 (примерно соответствует Windows 8.1) и знаю, что на нем установлена ​​новейшая платформа .NET Framework, а также новейшая оболочка Windows PowerShell. В PowerShell $PSVersionTableраскрывает версию PS что-то с 5.1. Этот PowerShell предназначен для .NET Framework (CLR) версии 4. *, которая, как я знаю, является новой для этой машины. Еще [cultureinfo]::GetCultureInfo("en-US").NumberFormat.PositiveInfinitySymbolиз Windows PowerShell выдает Infinity, а не (текущая культура есть en-US). Вывод: решает версия Windows, а не версия .NET.
Джеппе Стиг Нильсен
0

«8» для бесконечности отображается в консоли при запуске .Net 4 и выше, в противном случае предыдущие версии отображают «Бесконечность».

Using Console.OutputEncoding = Encoding.Unicode; в .Net 4 и выше бесконечность будет отображаться как ∞, но в предыдущих версиях выдает исключение IOException.

ПРИМЕЧАНИЕ. Я использую Visual Studio 2015 Community Edition в 64-разрядной версии Windows 10.

Дэйв Рассел
источник