¿Por qué se imprime infinito como "8" en la consola de Windows 10?

146

Estaba probando lo que se devolvió de la división, incluidos ceros 0/1, es decir , 1/0y 0/0. Para esto utilicé algo similar a lo siguiente:

Console.WriteLine(1d / 0d);

Sin embargo, este código 8no imprime Infinityo alguna otra cadena constante como PositiveInfinity.

Para completar todas las siguientes impresiones 8:

Console.WriteLine(1d / 0d);

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

Console.WriteLine(Double.PositiveInfinity);

Y Console.WriteLine(Double.NegativeInfinity);grabados -8.

¿Por qué este infinito imprime 8?


Para aquellos de ustedes que parecen pensar que este es un símbolo de infinito, no un ocho, el siguiente programa:

Console.WriteLine(1d / 0d);

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

Console.WriteLine(Double.PositiveInfinity);

Console.WriteLine(8);

Salidas:

Salida de la infinitud

TheLethalCoder
fuente
69
Ves es el signo del infinito. solo voltéalo 90 grados para verlo 8
Mohit Shrivastava
23
¿Estás seguro de que es un 8personaje Unicode real , no extraño para infinito, girado 90 grados? Esto podría cambiar en función de su entorno local. Lo probé en dotnetfiddle.net y se imprime Infinity.
Kroltan
44
@TheLethalCoder Haga lo que sugirió Sinatr o imprima el resultado Double.PositiveInfinity.ToString()[0] == '8'. Hay algunos caracteres exóticos que se parecen mucho a otros en algunas fuentes. Además, ¿en qué idioma está configurada su computadora?
Kroltan
15
Esto parece ser un problema de Windows 10. En Windows 8.1 tenía un símbolo de infinito. Actualicé hace unos días a Windows 10 y ahora también tengo una 8(configuración regional en alemán).
René Vogt
13
Una comprobación rápida sería ver qué sucedeConsole.Write("∞");
Jon Hanna,

Respuestas:

110

Tenga la seguridad de que el valor de coma flotante es +Infinitysi el numerador de una división de coma flotante por cero es positivo, -Infinitysi el numerador de una división de coma flotante por cero es negativo, y NaNsi el numerador y el denominador de una división de coma flotante son ambos cero. Eso está en la especificación de punto flotante IEEE754 , que es lo que usa C #.

En su caso, la consola está convirtiendo el símbolo de infinito (que a veces se representa tipográficamente como un 8 - horizontal horizontal) en un 8 vertical.

Betsabé
fuente
13
@TheLethalCoder La imagen no refuta esta respuesta, ya que es una imagen de tu consola
Rob
9
@Rob Leí mal la respuesta, sin embargo, eso plantea las preguntas, ¿por qué lo convierte a 8? ¿Y por qué algunos violines / consolas imprimen el literal de cadena
TheLethalCoder
1
Este parece ser el caso usando el depurador. Veo un símbolo de infinito (es decir, el 8 horizontal), ¿hay alguna razón por la cual mi consola se convertiría en un 8 mientras que el resto parece usar Infinityo similar, incluso si uso el código de la respuesta? Soren al especificar la cultura
TheLethalCoder
44
Se llama "lemniscate". Tiene un valor unicode: ∞
BlueRaja - Danny Pflughoeft
14
Esto probablemente explica por qué Buzz Lightyear dice "¡A ocho y más! cuando juego Toy Story en mi PC. ;)
DeanOC
70

Dadas ciertas configuraciones (es decir, combinación de culturas, codificación de salida, etc.) .NET generará el carácter de infinito Unicode ∞ (∞ / & # 8734;). El emulador de consola / terminal de Windows 10 (una vez más, dada cierta configuración, vea la captura de pantalla a continuación) mostrará este carácter Unicode como un 8.

Por ejemplo, en Windows 10, con la configuración a continuación (observe la página de códigos) simplemente pegando ∞ en la consola se muestra como 8.

Ajuste para reproducir

EDITAR

Con agradecimiento al comentario de Chris : Parece que la fuente de salida en combinación con la página de códigos es responsable del problema ∞ => 8 en la consola. Al igual que él, obtengo una visualización adecuada de ∞ en todas las fuentes TrueType que he probado y solo veo 8 cuando se selecciona 'fuentes ráster'.

configuración de fuente

tolanj
fuente
1
El mío en realidad muestra el signo de infinito a su lado en lugar de un "8" cuando se pega en la consola, aunque estoy usando "437 (OEM - Estados Unidos)"
Derek 朕 會 功夫
3
Aunque la respuesta es correcta, ciertas configuraciones pueden causar este problema de visualización, la segunda mitad es incorrecta. Actualmente, mis opciones son exactamente las mismas que las anteriores y obtengo el ∞ correcto en lugar de un 8. Solo puedo hacer que muestre un 8 si voy a la página de fuentes y elijo "fuentes ráster" de la lista de fuentes disponibles. Consolas, Courier New y otros parecen mostrarlo bien ...
Chris
Definitivamente es una combinación de los dos factores, porque establecer la fuente en Ráster cuando la página de códigos es 437 todavía muestra el símbolo correctamente. Solo si se cumplen ambas condiciones, esto parece suceder (al menos para mí).
Moshe Katz
39

El 8símbolo aparece cuando Windows convierte Unicode en una codificación de caracteres heredada. Como no hay un símbolo de infinito en la codificación heredada, utiliza un "mejor ajuste" a ese símbolo, de forma predeterminada , que en este caso es el número 8. Vea un ejemplo para la codificación "windows-1252" de Microsoft . Aparentemente, Windows 10 todavía usa codificaciones de caracteres heredados por defecto en la consola (consulte "Páginas de códigos" ).

Peter O.
fuente
11
Me pregunto por qué "8" se considera un buen ajuste, cuando es semánticamente tan apto para generar confusión. Otros caracteres en la página de códigos 437 parecen encajar mejor, como el signo de grado o el signo por mil (un% con dos o debajo de la barra). Ninguno de los dos sería tan bueno como un signo de infinito real, pero parecerían menos propensos a causar confusión.
supercat
"Aparentemente, Windows 10 todavía usa codificaciones de caracteres heredados por defecto en la consola" No, mi Windows 10 cmd.exe tiene la codificación heredada desactivada de fábrica .
Carreras de ligereza en órbita el
Esta es la mejor respuesta en mi humilde opinión. En realidad, también puede ver el carácter '8' en la posición 0x2440 al menos en mi cuadro de Windows 10 en el archivo c: \ windows \ system32 \ c_1252.nls (el infinito es 0x221E, y el archivo tiene un encabezado que explica el desplazamiento) . Toda la codificación de la página de códigos tiene un archivo .nls correspondiente. Por defecto, la consola usa la página de códigos 1252 (Windows 1252). Tenga en cuenta que estas asignaciones no se mantendrán, consulte esto: blogs.msdn.microsoft.com/shawnste/2007/09/24/…
Simon Mourier
35

Nota: La .ToString()llamada al método implícito al escribir Double.PositiveInfinityen la consola es responsable de este comportamiento.

Vocación Console.WriteLine(Double.PositiveInfinity.ToString(new CultureInfo("en-Us")));

da como resultado la cadena "Infinito"

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

Editar: como otros han señalado en los comentarios, no pueden confirmar completamente mis resultados. Al probar esto en una máquina diferente, obtengo el carácter para ambas llamadas.

Salida para todas las culturas , gracias a vtortola en los comentarios.


Encontré una respuesta (probable):

Usando Console.OutputEncoding = Encoding.Unicode;puedo recrear el comportamiento que está experimentando para varias culturas, por ejemplo, "ru", "ru-RU" producen el resultado 8.

Søren D. Ptæus
fuente
1
Por interés probé tus ejemplos y ambos imprimen 8
TheLethalCoder
1
@TheLethalCoder Me meto Infinityen ambos. ¿Cuál es la cultura que ejecuta su aplicación? Compruebe Thread.CurrentThread.CurrentCulturey Thread.CurrentThread.CurrentUICulture.
vtortola
8
@ Søren D. Ptæus tbh No puedo ver ninguna cultura que genere un 8 dotnetfiddle.net/QYhXMu
vtortola
1
Tienes razón sobre lo implícito .ToString(). Al final, ToString()devolverá el .PositiveInfinitySymbolde lo relevante NumberFormatInfo. Estos parecen depender de la versión del tiempo de ejecución y / o la versión de Windows (o cualquier sistema operativo). En los viejos tiempos, CultureInfo.GetCultureInfo("en-US").NumberFormat.PositiveInfinitySymbolsería igual a "Infinity", pero con versiones más nuevas del tiempo de ejecución y el sistema operativo lo es "∞". Solo pregunté al respecto en un comentario a la respuesta de Hans Passant en este hilo.
Jeppe Stig Nielsen
16

Código de 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();
    }
}

La página de códigos 1252 es un accidente bastante común en Inglaterra ya que es la página de códigos predeterminada de Windows allí. Como lo es para Europa Occidental y las Américas. Muchas razones para cambiar la propiedad predeterminada Console.OutputEncoding mediante programación, muchos archivos de texto se codificarán en 1252. O desde la línea de comandos escribiendo chcp 1252(chcp == cambiar página de códigos) antes de iniciar el programa.

Como puede deducir del conjunto de caracteres admitido por 1252, el símbolo Infinito no está disponible. Entonces la codificación tiene que llegar a un sustituto. Ese es a menudo el ?glifo para puntos de código Unicode no compatibles, el valor de la propiedad Encoding.EncoderFallback para codificaciones de 8 bits. Pero para 1252, y las antiguas páginas de códigos MS-Dos 850 y 858, el programador de Microsoft decidió 8. Chico divertido.

El glifo es compatible con la página de códigos habitual para aplicaciones de consola en una máquina occidental. Que es 437, coincide con el juego de caracteres heredado de IBM . Tener este tipo de desastres de codificación es la razón por la cual se inventó Unicode. Lamentablemente, es demasiado tarde para rescatar aplicaciones de consola, demasiado código que dependía de la página de códigos MS-Dos predeterminada.

Tener Double.PositiveInfinity convertido a "∞" es específico de Win10. Solía ​​ser "Infinito" en versiones anteriores de Windows. Este tipo de formatos normalmente se puede modificar con el Panel de control> Idioma> Cambiar formatos de fecha, hora o número> botón Configuración adicional, pero la selección del símbolo de infinito no se incluye en el cuadro de diálogo. Tampoco está cubierto por el registro (HKCU \ Control Panel \ International), sino una gran supervisión. Es LOCALE_SPOSINFINITY en el winapi nativo. En un programa .NET, puede anularlo mediante programación clonando CultureInfo y cambiando su propiedad NumberFormatInfo.PositiveInfinitySymbol. Me gusta esto:

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
fuente
Su código me permitió confirmar que WinXP usa la página de códigos 437, que, en Windows 10, ahora se imprime en ýlugar de . También me mostró que el uso de fuentes no ráster evita el problema.
Mark Hurd
¿Es la versión del tiempo de ejecución de .NET, o la versión de Windows (o cualquier sistema operativo), o una combinación, lo que determina si se CultureInfo.GetCultureInfo("en-US").NumberFormat.PositiveInfinitySymbolda "Infinity"o "∞"(o algo más)? Usted dice anteriormente que es específico de Windows 10, y estoy de acuerdo en que se modificó en algún momento. Pero si ejecuto una aplicación en Windows 8 con "la misma" versión de .NET Framework , ¿obtendré un resultado diferente que con Windows 10?
Jeppe Stig Nielsen
Este problema comienza con Windows, luego expone una peculiaridad en .NET. Win8 todavía favorece "Infinity"
Hans Passant
1
¡Confirmado! Acabo de iniciar sesión en un equipo con Windows Server 2012 R2 (corresponde aproximadamente a Windows 8.1), y sé que tiene el .NET Framework más nuevo, y también tiene el Windows PowerShell más nuevo. En PowerShell, $PSVersionTablerevela que la versión PS es algo con 5.1. Ese PowerShell está dirigido a .NET Framework (CLR) versión 4. *, que sé que es nuevo en esa máquina. Todavía [cultureinfo]::GetCultureInfo("en-US").NumberFormat.PositiveInfinitySymbolde Windows PowerShell da Infinity, no (la cultura actual es en-US). Conclusión: la versión de Windows decide, no la versión .NET.
Jeppe Stig Nielsen
0

"8" para infinito se muestra en la consola cuando se ejecuta .Net 4 y superior, de lo contrario, las versiones anteriores muestran "Infinito".

Usando Console.OutputEncoding = Encoding.Unicode; en .Net 4 y superior obtendrá infinito para mostrar como ∞, pero arroja una IOException en versiones anteriores.

NOTA: estoy ejecutando Visual Studio 2015 Community Edition en Windows 10 de 64 bits

Dave Russell
fuente