Pourquoi l'infini est-il imprimé comme «8» dans la console Windows 10?

146

Je testais ce qui était retourné de la division, y compris les zéros, c'est 0/1-à- dire 1/0et 0/0. Pour cela, j'ai utilisé quelque chose de similaire à ce qui suit:

Console.WriteLine(1d / 0d);

Cependant, ce code n'imprime 8pas Infinityou une autre constante de chaîne comme PositiveInfinity.

Par souci d'exhaustivité, toutes les impressions suivantes 8:

Console.WriteLine(1d / 0d);

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

Console.WriteLine(Double.PositiveInfinity);

Et des Console.WriteLine(Double.NegativeInfinity);impressions -8.

Pourquoi cet infini imprime-t-il 8?


Pour ceux d'entre vous qui semblent penser que c'est un symbole de l'infini et non un huit le programme suivant:

Console.WriteLine(1d / 0d);

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

Console.WriteLine(Double.PositiveInfinity);

Console.WriteLine(8);

Les sorties:

Sortie Inifinity

TheLethalCoder
la source
69
Vous voyez, c'est le signe de l'infini. il suffit de le retourner à 90 degrés pour le voir 8
Mohit Shrivastava
23
Êtes-vous sûr que c'est un 8caractère Unicode réel , pas un étrange caractère pour l'infini, pivoté de 90 degrés? Cela pourrait changer en fonction de vos paramètres régionaux. Je l'ai essayé sur dotnetfiddle.net et il s'imprime Infinity.
Kroltan
4
@TheLethalCoder Veuillez faire ce que Sinatr a suggéré, ou imprimer la sortie de Double.PositiveInfinity.ToString()[0] == '8'. Certains caractères exotiques ressemblent beaucoup à d'autres dans certaines polices. De plus, dans quelle langue votre ordinateur est-il configuré?
Kroltan
15
Cela semble être un problème de Windows 10. Dans Windows 8.1, j'avais un symbole de l'infini. Mise à niveau il y a quelques jours vers Windows 10 et maintenant j'ai aussi un 8(langue allemande).
René Vogt
13
Une vérification rapide serait de voir ce qui se passe pourConsole.Write("∞");
Jon Hanna

Réponses:

110

Soyez assuré que la valeur en virgule flottante est +Infinitysi le numérateur d'une division en virgule flottante par zéro est positif, -Infinitysi le numérateur d'une division en virgule flottante par zéro est négatif, et NaNsi le numérateur et le dénominateur d'une division en virgule flottante sont tous deux zéro. C'est dans la spécification à virgule flottante IEEE754 , ce qu'utilise C #.

Dans votre cas, la console convertit le symbole de l'infini (qui est parfois représenté typographiquement comme un 8 horizontal - ∞) en un 8 vertical.

Bathsheba
la source
13
@TheLethalCoder La photo ne réfute pas cette réponse, car c'est une photo de votre console
Rob
9
@Rob J'ai mal lu la réponse, mais cela soulève des questions, pourquoi la convertit-elle en 8? Et pourquoi certains violons / consoles impriment-ils la chaîne littérale
TheLethalCoder
1
Cela semble être le cas en utilisant le débogueur Je vois un symbole de l'infini (c'est-à-dire le 8 horizontal), y a-t-il une raison pour laquelle ma console se convertirait en 8 alors que tout le monde semble utiliser Infinityou similaire même si j'utilise le code de la réponse par Soren en spécifiant la culture
TheLethalCoder
4
C'est ce qu'on appelle un «lemniscate». Il a une valeur unicode: ∞
BlueRaja - Danny Pflughoeft
14
Cela explique probablement pourquoi Buzz Lightyear dit "To Eight And Beyond!" lorsque je joue à Toy Story sur mon PC. ;)
DeanOC
70

Compte tenu de certains paramètres (par exemple, combinaison de cultures, encodage de sortie, etc.) .NET affichera le caractère infini Unicode ∞ (∞ / & # 8734;). L'émulateur de console / terminal Windows 10 affichera (encore une fois certains paramètres - voir capture d'écran ci-dessous) ce caractère Unicode sous la forme d'un 8.

Par exemple, sur Windows 10, avec les paramètres ci-dessous (notez la page de codes), il suffit de coller ∞ dans la console comme 8.

Réglage pour reproduire

ÉDITER

Remerciements au commentaire de Chris : Il semble que la police de sortie en combinaison avec la page de codes soit responsable du problème ∞ => 8 sur la console. Comme lui, j'obtiens un affichage correct de ∞ dans toutes les polices TrueType que j'ai essayées et je ne vois 8 que lorsque les polices raster sont choisies.

paramètres de police

tolanj
la source
1
Le mien montre en fait le signe de l'infini sur son côté au lieu d'un "8" lorsqu'il est collé dans la console, bien que j'utilise "437 (OEM - États-Unis)"
Derek 朕 會 功夫
3
Bien que la réponse soit juste, certains paramètres peuvent causer ce problème d'affichage, la seconde moitié est incorrecte. Mes options sont actuellement exactement les mêmes que les vôtres ci-dessus et j'obtiens le bon ∞ plutôt qu'un 8. Je ne peux l'obtenir pour afficher un 8 que si je vais à la page des polices et que je choisis "polices raster" dans la liste des polices disponibles. Consolas, Courier New et d'autres semblent tous l'afficher bien ...
Chris
C'est certainement une combinaison des deux facteurs, car définir la police sur Raster lorsque la page de codes est 437 affiche toujours le symbole correctement. Ce n'est que si les deux conditions sont remplies que cela semble se produire (du moins pour moi).
Moshe Katz
39

Le 8symbole se produit lorsque Windows convertit Unicode en un encodage de caractères hérité. Puisqu'il n'y a pas de symbole infini dans le codage hérité, il utilise un "meilleur ajustement" à ce symbole, par défaut , qui dans ce cas est le numéro 8. Voir un exemple pour le codage "windows-1252" de Microsoft . Apparemment, Windows 10 utilise toujours les encodages de caractères hérités par défaut dans la console (voir «Pages de code» ).

Peter O.
la source
11
Je me demande pourquoi "8" est considéré comme un bon ajustement, alors qu'il est sémantiquement si susceptible de générer de la confusion? D'autres caractères de la page de codes 437 sembleraient mieux adaptés, comme le signe de degré ou le signe pour mille (un% avec deux o sous la barre oblique). Aucun de ceux-ci ne serait aussi bon qu'un signe d'infini réel, mais ils sembleraient moins susceptibles de semer la confusion.
supercat
"Apparemment, Windows 10 utilise toujours les codages de caractères hérités par défaut dans la console" Non, mon Windows 10 cmd.exe a le codage hérité désactivé dès la sortie de la boîte.
Courses de légèreté en orbite
C'est la meilleure réponse à mon humble avis. En fait, vous pouvez également voir le caractère '8' à la position 0x2440 au moins sur ma boîte Windows 10 dans le fichier c: \ windows \ system32 \ c_1252.nls (l' infini est 0x221E, et le fichier a un en-tête qui explique le décalage) . Tous les encodages de pages de codes ont un fichier .nls correspondant. Par défaut, la console utilise la page de codes 1252 (Windows 1252). Notez que ces mappages ne seront pas conservés, vérifiez ceci: blogs.msdn.microsoft.com/shawnste/2007/09/24/…
Simon Mourier
35

Remarque: L' .ToString()appel de méthode implicite lors de l'écriture Double.PositiveInfinitysur la console est responsable de ce comportement.

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

renvoie la chaîne "Infinity"

tandis que le Console.WriteLine(Double.PositiveInfinity.ToString(new CultureInfo("fr-Fr"))); résultat est "+ Infini".

Edit: Comme d'autres l'ont souligné dans les commets, ils ne peuvent pas confirmer entièrement mes résultats. En testant cela sur une machine différente, j'obtiens le personnage pour les deux appels.

Sortie pour toutes les cultures , grâce à vtortola dans les commentaires.


J'ai trouvé une réponse (probable):

En utilisant Console.OutputEncoding = Encoding.Unicode;je peux recréer le comportement que vous rencontrez pour plusieurs cultures, par exemple "ru", "ru-RU" produisent la sortie 8.

Søren D. Ptæus
la source
1
Par intérêt, j'ai essayé vos exemples et ils impriment tous les deux 8
TheLethalCoder
1
@TheLethalCoder J'entre Infinitydans les deux. Quelle est la culture utilisée par votre application? Vérifiez Thread.CurrentThread.CurrentCultureet Thread.CurrentThread.CurrentUICulture.
vtortola
8
@ Søren D. Ptæus tbh Je ne vois aucune culture générant un 8 dotnetfiddle.net/QYhXMu
vtortola
1
Vous avez raison sur l'implicite .ToString(). En fin de compte, ToString()retournera le .PositiveInfinitySymbolde la pertinente NumberFormatInfo. Celles-ci semblent dépendre de la version du runtime et / ou de la version de Windows (ou quel que soit le système d'exploitation). Dans l'ancien temps, ce CultureInfo.GetCultureInfo("en-US").NumberFormat.PositiveInfinitySymbolserait égal à "Infinity", mais avec les nouvelles versions du runtime et du système d'exploitation, c'est à la "∞"place. Je viens de poser une question à ce sujet dans un commentaire à la réponse de Hans Passant dans ce fil.
Jeppe Stig Nielsen
16

Code 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 page de codes 1252 est un accident assez courant en Angleterre car il s'agit de la page de codes Windows par défaut. Comme c'est le cas pour l'Europe occidentale et les Amériques. Beaucoup de raisons pour changer la propriété par défaut Console.OutputEncoding par programme, de nombreux fichiers texte seront encodés en 1252. Ou à partir de la ligne de commande en tapant chcp 1252(chcp == changer la page de code) avant de démarrer le programme.

Comme vous pouvez le voir d'après le jeu de caractères pris en charge par 1252, le symbole Infinity n'est pas disponible. Le codage doit donc proposer un substitut. Il s'agit souvent du ?glyphe des points de code Unicode non pris en charge, la valeur de la propriété Encoding.EncoderFallback pour les encodages 8 bits. Mais pour 1252 et les anciennes pages de codes MS-Dos 850 et 858, le programmeur Microsoft a opté pour 8. Mec marrant.

Le glyphe est pris en charge dans la page de codes habituelle des applications console sur une machine occidentale. Ce qui est 437, correspond à l'ancien jeu de caractères IBM . Avoir ce genre de désastres de codage est la raison pour laquelle Unicode a été inventé. Malheureusement, il est trop tard pour sauver les applications de la console, beaucoup trop de code qui reposait sur la page de codes MS-Dos par défaut.

La conversion de Double.PositiveInfinity en "∞" est spécifique à Win10. C'était "Infinity" dans les versions précédentes de Windows. Ces types de formats peuvent normalement être modifiés avec Panneau de configuration> Langue> Modifier les formats de date, d'heure ou de nombre> bouton Paramètres supplémentaires, mais la sélection du symbole de l'infini n'est pas incluse dans la boîte de dialogue. Également non couvert par le registre (HKCU \ Control Panel \ International), plutôt un gros oubli. Il s'agit de LOCALE_SPOSINFINITY dans le winapi natif. Dans un programme .NET, vous pouvez le remplacer par programme en clonant le CultureInfo et en modifiant sa propriété NumberFormatInfo.PositiveInfinitySymbol. Comme ça:

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
la source
Votre code m'a permis de confirmer que WinXP utilise la page de code 437, qui, dans Windows 10, s'imprime désormais à la ýplace de . Cela m'a également montré que l'utilisation de polices non raster évitait le problème.
Mark Hurd
Est-ce la version du runtime .NET, ou la version de Windows (ou n'importe quel système d'exploitation), ou une combinaison, qui détermine si CultureInfo.GetCultureInfo("en-US").NumberFormat.PositiveInfinitySymboldonne "Infinity"ou "∞"(ou autre chose)? Vous dites ci-dessus qu'il est spécifique à Windows 10, et je suis d'accord qu'il a été modifié à un moment donné. Mais si j'exécute une application sur Windows 8 avec «la même» version du .NET Framework , est-ce que j'obtiendrai un résultat différent de celui de Windows 10?
Jeppe Stig Nielsen
Ce problème commence avec Windows, puis expose une bizarrerie dans .NET. Win8 privilégie toujours "Infinity"
Hans Passant
1
Confirmé! Je viens de me connecter à une machine Windows Server 2012 R2 (correspond à peu près à Windows 8.1), et je sais qu'elle dispose du dernier .NET Framework, ainsi que du dernier Windows PowerShell. Dans PowerShell, $PSVersionTablerévèle que la version PS est quelque chose avec 5.1. Ce PowerShell cible le .NET Framework (CLR) version 4. * que je sais est nouveau sur cette machine. Toujours [cultureinfo]::GetCultureInfo("en-US").NumberFormat.PositiveInfinitySymbolde Windows PowerShell donne Infinity, non (la culture actuelle est en-US). Conclusion: c'est la version Windows qui décide, pas la version .NET.
Jeppe Stig Nielsen
0

"8" pour l'infini est affiché dans la console lors de l'exécution de .Net 4 et supérieur, sinon les versions précédentes affichent "Infinity".

Utilisation de Console.OutputEncoding = Encoding.Unicode; dans .Net 4 et au-dessus obtiendra l'infini pour s'afficher comme ∞, mais lèvera une IOException dans les versions précédentes.

REMARQUE: j'exécute Visual Studio 2015 Community Edition sur Windows 10 64 bits

Dave Russell
la source