Por que o infinito é impresso como "8" no console do Windows 10?

146

Eu estava testando o que foi retornado da divisão, incluindo zeros 0/1, ie , 1/0e 0/0. Para isso, usei algo semelhante ao seguinte:

Console.WriteLine(1d / 0d);

No entanto, esse código 8não imprime Infinityou alguma outra string constante como PositiveInfinity.

Para completar, todas as seguintes impressões 8:

Console.WriteLine(1d / 0d);

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

Console.WriteLine(Double.PositiveInfinity);

E Console.WriteLine(Double.NegativeInfinity);imprime -8.

Por que esse infinito imprime 8?


Para aqueles que parecem pensar que este é um símbolo do infinito e não um oito, o seguinte programa:

Console.WriteLine(1d / 0d);

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

Console.WriteLine(Double.PositiveInfinity);

Console.WriteLine(8);

Saídas:

Saída Inifinity

TheLethalCoder
fonte
69
Você vê é o sinal do infinito. basta girá-lo 90 graus para vê-lo 8
Mohit Shrivastava
23
Tem certeza de que é um 8caractere Unicode real , não estranho, para o infinito, girado 90 graus? Isso pode mudar com base no seu código de idioma. Eu tentei no dotnetfiddle.net e ele imprime Infinity.
Kroltan
4
@TheLethalCoder Por favor, faça o que Sinatr sugeriu ou imprima a saída de Double.PositiveInfinity.ToString()[0] == '8'. Existem alguns caracteres exóticos que se parecem muito com outros em algumas fontes. Além disso, em qual idioma o seu computador está configurado?
Kroltan 01/12/16
15
Este parece ser um problema do Windows 10. No Windows 8.1, eu tinha um símbolo do infinito. Atualizei há alguns dias para o Windows 10 e agora também tenho um 8(localidade alemã).
René Vogt
13
Uma verificação rápida seria para ver o que aconteceConsole.Write("∞");
Jon Hanna -

Respostas:

110

Certifique-se de que o valor do ponto flutuante seja +Infinityse o numerador de uma divisão de ponto flutuante por zero for positivo, -Infinityse o numerador de uma divisão de ponto flutuante por zero for negativo e NaNse o numerador e o denominador de uma divisão de ponto flutuante forem zero. Isso está na especificação de ponto flutuante IEEE754 , que é o que o C # usa.

No seu caso, o console está convertendo o símbolo do infinito (que às vezes é representado tipograficamente como um 8 - horizontal horizontal) em um 8 vertical.

Bathsheba
fonte
13
@TheLethalCoder A imagem não refutar esta resposta, uma vez que é um retrato de seu console
Rob
9
@ Rob Eu interpretei mal a resposta, no entanto, isso levanta as perguntas, por que a converte em um 8? E porque é que alguns violinos / consoles imprimir o literal de cadeia
TheLethalCoder
1
Esse parece ser o caso do depurador. Eu vejo um símbolo do infinito (ou seja, o 8 horizontal). Existe algum motivo para o meu console ser convertido em 8, enquanto todo mundo parece usar Infinityou semelhante, mesmo que eu use o código da resposta por Soren especificando a cultura
TheLethalCoder 1/16/16
4
É chamado de "lemniscate". Tem um valor unicode: ∞
BlueRaja - Danny Pflughoeft
14
Isso provavelmente explica por que o Buzz Lightyear diz "To Eight And Beyond!" quando jogo Toy Story no meu PC. ;)
DeanOC 6/16
70

Dadas determinadas configurações (por exemplo, combinação de culturas, codificação de saída etc.), o .NET emitirá o caractere infinito Unicode ∞ (∞ / & # 8734;). O emulador de console / terminal do Windows 10 (novamente com determinadas configurações - veja a captura de tela abaixo) exibirá esse caractere Unicode como um 8.

Por exemplo, no Windows 10, com as configurações abaixo (observe a página de códigos), basta colar ∞ no console como 8.

Definindo para reproduzir

EDITAR

Com agradecimentos ao comentário de Chris : Parece que a fonte de saída em combinação com a página de código é responsável pelo problema ∞ => 8 no console. Como ele, obtenho uma exibição adequada de ∞ em todas as fontes TrueType que eu tentei e só vejo 8 quando as fontes raster 'são escolhidas.

configurações de fonte

tolanj
fonte
1
Mina realmente mostra o sinal de infinito em seu lado em vez de um "8" quando colado no console, embora eu estou usando "437 (OEM - Estados Unidos)"
Derek朕會功夫
3
Embora a resposta esteja certa de que certas configurações podem causar esse problema de exibição, a segunda metade está incorreta. Atualmente, minhas opções são exatamente iguais às suas e eu obtenho o correct correto, em vez de 8. Eu só consigo mostrar um 8 se eu for para a página de fontes e escolher "fontes de varredura" na lista de fontes disponíveis. Consolas, Courier New e outros, todos parecem exibi-lo bem ...
Chris
Definitivamente, é uma combinação dos dois fatores, porque definir a fonte como Raster quando a página de código é 437 ainda mostra o símbolo corretamente. Somente se as duas condições forem atendidas isso parece acontecer (pelo menos para mim).
Moshe Katz
39

O 8símbolo ocorre quando o Windows converte Unicode em uma codificação de caracteres herdados. Como não há símbolo de infinito na codificação herdada, ele usa um "melhor ajuste" para esse símbolo, por padrão , que neste caso é o número 8. Veja um exemplo da codificação "windows-1252" da Microsoft . Aparentemente, o Windows 10 ainda usa codificações de caracteres herdadas por padrão no console (consulte "Páginas de código" ).

Peter O.
fonte
11
Eu me pergunto por que "8" é considerado um bom ajuste, quando é semanticamente tão apto a gerar confusão? Outros caracteres na página de código 437 pareceriam mais adequados, como o sinal de grau ou por milha (uma% com dois o abaixo da barra). Nenhum deles seria tão bom quanto um sinal de infinito real, mas eles pareceriam menos propensos a causar confusão.
Supercat 2/16
"Aparentemente, o Windows 10 ainda usa codificações de caracteres herdadas por padrão no console" Não, meu Windows 10 cmd.exe tem a codificação herdada desativada.
Lightness Races in Orbit
Esta é a melhor resposta IMHO. Na verdade, você também pode ver o caractere '8' na posição 0x2440 pelo menos na minha caixa do Windows 10 no arquivo c: \ windows \ system32 \ c_1252.nls (o infinito é 0x221E e o arquivo tem algum cabeçalho que explica o deslocamento) . Toda codificação de página de código tem um arquivo .nls correspondente. Por padrão, o console usa a página de código 1252 (Windows 1252). Observe que esses mapeamentos não serão mantidos, verifique o seguinte: blogs.msdn.microsoft.com/shawnste/2007/09/24/…
Simon Mourier
35

Nota: A .ToString()chamada implícita do método ao gravar Double.PositiveInfinityno console é responsável por esse comportamento.

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

resulta na string "Infinito"

enquanto Console.WriteLine(Double.PositiveInfinity.ToString(new CultureInfo("fr-Fr"))); resulta em "+ Infini".

Edit: Como outros já apontaram nos commets, eles não podem confirmar totalmente meus resultados. Testando isso em uma máquina diferente, recebo o caractere para as duas chamadas.

Saída para todas as culturas , graças a vtortola nos comentários.


Encontrei uma resposta (provável):

Usando Console.OutputEncoding = Encoding.Unicode;Eu posso recriar o comportamento que você está enfrentando para várias culturas, por exemplo, "ru", "ru-RU" produz a saída 8.

Søren D. Ptæus
fonte
1
Fora de interesse Eu tentei seus exemplos e ambos impressão 8
TheLethalCoder
1
@TheLethalCoder eu entro Infinitynos dois. Qual é a cultura que seu aplicativo está executando? Verifique Thread.CurrentThread.CurrentCulturee Thread.CurrentThread.CurrentUICulture.
Vtortola
8
@ Søren D. Ptæus tbh Não consigo ver nenhuma cultura gerando um 8 dotnetfiddle.net/QYhXMu
vtortola
1
Você está certo sobre o implícito .ToString(). No final, ToString()retornará o .PositiveInfinitySymboldo relevante NumberFormatInfo. Eles parecem depender da versão do tempo de execução e / ou da versão do Windows (ou de qualquer SO). Antigamente, CultureInfo.GetCultureInfo("en-US").NumberFormat.PositiveInfinitySymbolseria igual a "Infinity", mas nas versões mais recentes do tempo de execução e do sistema operacional, é o mesmo "∞". Eu apenas perguntei sobre isso em um comentário à resposta de Hans Passant neste tópico.
Jeppe Stig Nielsen
16

Código de reprodução:

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

A página de código 1252 é um acidente bastante comum na Inglaterra, pois é a página de código padrão do Windows lá. Como é para a Europa Ocidental e as Américas. Vários motivos para alterar a propriedade padrão Console.OutputEncoding programaticamente, muitos arquivos de texto serão codificados em 1252. Ou na linha de comando, digitandochcp 1252 (chcp == alterar a página de código) antes de iniciar o programa.

Como você pode ver no conjunto de caracteres suportado por 1252, o símbolo Infinito não está disponível. Portanto, a codificação precisa de um substituto. Esse geralmente é o ?glifo para pontos de código Unicode não suportados, o valor da propriedade Encoding.EncoderFallback para codificações de 8 bits. Mas, para 1252, e as páginas de códigos herdadas do MS-Dos 850 e 858, o programador da Microsoft decidiu8 . Cara engraçado.

O glifo é suportado na página de códigos usual para aplicativos de console em uma máquina Western. Qual é 437, corresponde ao conjunto de caracteres herdado da IBM . Ter esse tipo de desastre de codificação é o motivo pelo qual o Unicode foi inventado. Infelizmente, é tarde demais para resgatar aplicativos de console, muito código em torno dele se baseia na página de código padrão do MS-Dos.

A conversão de Double.PositiveInfinity para "∞" é específica do Win10. Costumava ser "Infinito" nas versões anteriores do Windows. Normalmente, esses tipos de formatos podem ser modificados com o botão Painel de controle> Idioma> Alterar formatos de data, hora ou número> Configurações adicionais, mas a seleção do símbolo de infinito não está incluída na caixa de diálogo. Também não é coberto pelo registro (HKCU \ Control Panel \ International), mas por uma grande supervisão. É LOCALE_SPOSINFINITY no winapi nativo. Em um programa .NET, você pode substituí-lo programaticamente, clonando o CultureInfo e alterando sua propriedade NumberFormatInfo.PositiveInfinitySymbol. Como isso:

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
fonte
Seu código me permitiu confirmar que o WinXP usa a página de código 437, que, no Windows 10, agora é impressa em ývez de . Também me mostrou que o uso de fontes não rasterizadas evita o problema.
Mark Hurd
É a versão do tempo de execução .NET, ou a versão do Windows (ou qualquer SO), ou uma combinação que determina se CultureInfo.GetCultureInfo("en-US").NumberFormat.PositiveInfinitySymbol"Infinity"ou "∞"(ou outra coisa)? Você diz acima que é específico para o Windows 10 e concordo que foi alterado em algum momento. Mas se eu executar um aplicativo no Windows 8 com a versão "mesma" do .NET Framework , obterá um resultado diferente do Windows 10?
Jeppe Stig Nielsen
Esse problema começa no Windows e expõe uma peculiaridade no .NET. Win8 ainda favorece "Infinito"
Hans Passant
1
Confirmado! Acabei de fazer login em uma máquina Windows Server 2012 R2 (corresponde aproximadamente ao Windows 8.1) e sei que possui o .NET Framework mais novo e também o Windows PowerShell. No PowerShell, $PSVersionTablerevela que a versão PS é algo com 5.1. Esse PowerShell tem como alvo o .NET Framework (CLR) versão 4. *, que eu sei que é novo nessa máquina. Ainda [cultureinfo]::GetCultureInfo("en-US").NumberFormat.PositiveInfinitySymboldo Windows PowerShell oferece Infinity, não (a cultura atual é en-US). Conclusão: a versão do Windows decide, não a versão do .NET.
Jeppe Stig Nielsen
0

"8" para infinito é exibido no console ao executar o .Net 4 e superior; caso contrário, as versões anteriores exibem "Infinito".

Using Console.OutputEncoding = Encoding.Unicode; no .Net 4 e acima, o infinito será exibido como ∞, mas lança uma IOException nas versões anteriores.

NOTA: Estou executando o Visual Studio 2015 Community Edition no Windows 10 de 64 bits

Dave Russell
fonte