为啥无穷大在 Windows 10 控制台中打印为“8”?
Posted
技术标签:
【中文标题】为啥无穷大在 Windows 10 控制台中打印为“8”?【英文标题】:Why is infinity printed as "8" in the Windows 10 console?为什么无穷大在 Windows 10 控制台中打印为“8”? 【发布时间】:2017-04-15 21:37:15 【问题描述】:我正在测试从除法返回的内容,包括零,即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);
输出:
【问题讨论】:
你看∞
是无穷大的标志。只需将其翻转 90 度即可看到 8
你确定它是一个实际的8
,而不是一些奇怪的无限的Unicode字符,旋转90度?这可能会根据您的语言环境而改变。我在dotnetfiddle.net 上尝试过,它打印出Infinity
。
@TheLethalCoder 请按照 Sinatr 的建议做,或者打印Double.PositiveInfinity.ToString()[0] == '8'
的输出。在某些字体中,有些外来字符看起来与其他字符非常相似。另外,您的计算机配置为哪种语言?
这似乎是 Windows 10 的问题。在 Windows 8.1 中,我有一个无穷大符号。几天前升级到 Windows 10,现在我也有一个 8
(德语区域设置)。
快速检查一下Console.Write("∞");
会发生什么
【参考方案1】:
确保浮点值是+Infinity
如果浮点除以零的分子是正数,-Infinity
如果浮点除以零的分子是负数,NaN
如果分子浮点除法的分母和分母都为零。那在IEEE754 floating point specification 中,这是C# 使用的。
在您的情况下,控制台正在将无穷大符号(有时在印刷上表示为水平 8 — ∞)转换为垂直 8。
【讨论】:
@TheLethalCoder 图片并不能反驳这个答案,因为它是您的控制台的图片 @Rob 我误读了答案,但这引出了问题,为什么将其转换为 8?为什么有些小提琴/控制台会打印字符串文字 这似乎是使用调试器的情况,我看到一个无穷大符号(即水平 8),有什么理由我的控制台会转换为 8 而其他人似乎都在使用Infinity
或即使我通过指定文化来使用 Soren 的答案中的代码,也相似
它被称为“双纽线”。它有一个 unicode 值:∞
这可能解释了为什么巴斯光年会说“到八岁及以上!”当我在 PC 上玩玩具总动员时。 ;)【参考方案2】:
给定某些设置(即文化组合、输出编码等),.NET 将输出 Unicode 无穷大字符 ∞ (∞ / ∞)。 Windows 10 控制台/终端模拟器将(再次给定某些设置 - 请参见下面的屏幕截图)将此 Unicode 字符显示为 8。
例如,在 Windows 10 上,使用以下设置(注意代码页)只需将 ∞ 粘贴到控制台中显示为 8。
编辑
感谢Chris的评论: 似乎输出字体结合代码页负责控制台上的∞ => 8问题。像他一样,我在我尝试过的所有 TrueType 字体中都能正确显示 ∞,并且在选择光栅字体时只看到 8。
【讨论】:
虽然我使用的是“437(OEM - 美国)”,但我在控制台中粘贴时实际上显示的是无穷大符号而不是“8” 虽然答案是正确的,某些设置可能会导致此显示问题,但后半部分是不正确的。我的选项目前看起来和你上面的完全一样,我得到了正确的∞而不是 8。如果我去字体页面并从可用字体列表中选择“光栅字体”,我只能让它显示 8。 Consolas、Courier New 和其他人似乎都显示得很好...... 这绝对是两个因素的结合,因为在代码页为 437 时将字体设置为 Raster 仍然可以正确显示符号。只有当 两个 条件都满足时,这似乎才会发生(至少对我而言)。【参考方案3】:8
符号出现在 Windows 将 Unicode 转换为旧字符编码时。由于传统编码中没有无穷大符号,因此它使用"best fit" to that symbol, by default,在本例中为数字 8。请参阅Microsoft's "windows-1252" encoding 的示例。显然,Windows 10 仍然在控制台中默认使用旧字符编码(请参阅"Code Pages")。
【讨论】:
我想知道为什么“8”被认为是一个很好的选择,而它在语义上很容易产生混淆?代码页 437 中的其他字符似乎更合适,例如度数符号或千分号(斜线下方带有两个 o 的 %)。这些都不如实际的无穷大符号好,但它们似乎不太容易引起混淆。 “显然,Windows 10 在控制台中默认仍使用旧版字符编码” 不,我的 Windows 10 cmd.exe 开箱即用地关闭了旧版编码。 这是最好的答案恕我直言。实际上,您还可以在 c:\windows\system32\c_1252.nls 文件(infinity 为 0x221E,文件有一些解释偏移量的标题)。所有代码页编码都有一个对应的 .nls 文件。默认情况下,控制台使用 1252 代码页 (Windows 1252)。注意这些映射不会被维护,检查这个:blogs.msdn.microsoft.com/shawnste/2007/09/24/…【参考方案4】:注意:将Double.PositiveInfinity
写入控制台时的隐式.ToString()
方法调用是造成此行为的原因。
打电话
Console.WriteLine(Double.PositiveInfinity.ToString(new CultureInfo("en-Us")));
产生字符串“Infinity”
而Console.WriteLine(Double.PositiveInfinity.ToString(new CultureInfo("fr-Fr")));
结果为“+Infini”。
编辑:正如其他人在评论中指出的那样,他们不能完全证实我的结果。在另一台机器上进行测试,我得到两个调用的字符 ∞
。
Output for all cultures,感谢 cmets 中的vtortola 。
我找到了一个(可能的)答案:
使用 Console.OutputEncoding = Encoding.Unicode;
我可以重现您在多种文化中遇到的行为,例如"ru", "ru-RU" 产生输出8
。
【讨论】:
出于兴趣,我尝试了您的示例,它们都打印了 8 @TheLethalCoder 我在两者中都得到了Infinity
。您的应用运行的文化是什么?检查Thread.CurrentThread.CurrentCulture
和Thread.CurrentThread.CurrentUICulture
。
@Søren D. Ptæus tbh 我看不到任何文化产生 8
dotnetfiddle.net/QYhXMu
您对隐含的.ToString()
是正确的。最后ToString()
会返回相关NumberFormatInfo
的.PositiveInfinitySymbol
。这些似乎取决于运行时的版本和/或 Windows(或任何操作系统)的版本。在过去,CultureInfo.GetCultureInfo("en-US").NumberFormat.PositiveInfinitySymbol
将等于 "Infinity"
,但对于较新版本的运行时和操作系统,则改为 "∞"
。我刚刚在对 Hans Passant 在此线程中的回答的评论中询问了这个问题。【参考方案5】:
复制代码:
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 支持的 the character set 可以看出,无穷大符号不可用。所以编码必须想出一个替代品。这通常是不支持的 Unicode 代码点的 ?
字形,8 位编码的 Encoding.EncoderFallback 属性值。但是对于 1252 以及遗留的 MS-Dos 850 和 858 代码页,Microsoft 程序员决定使用8
。有趣的家伙。
西方机器上控制台应用程序的常用代码页支持该字形。这是 437,matches the legacy IBM character set。出现这种编码灾难就是发明 Unicode 的原因。遗憾的是,拯救控制台应用程序为时已晚,太多的代码依赖于默认的 MS-Dos 代码页。
将 Double.PositiveInfinity 转换为“∞”是 Win10 特有的。在以前的 Windows 版本中,它曾经是“Infinity”。这些格式通常可以通过控制面板 > 语言 > 更改日期、时间或数字格式 > 其他设置按钮进行修改,但无限符号选择不包含在对话框中。注册表也没有涵盖(HKCU\Control Panel\International),这是一个很大的疏忽。在本机 winapi 中为 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 依然偏爱“无限”
确认!我刚刚登录了一台 Windows Server 2012 R2 机器(大致对应于 Windows 8.1),我知道它具有最新的 .NET Framework,并且还具有最新的 Windows PowerShell。在 PowerShell 中,$PSVersionTable
显示 PS 版本是 5.1。该 PowerShell 以 .NET Framework (CLR) 版本 4.* 为目标,我知道该版本在该机器上是新的。仍然来自 Windows PowerShell 的 [cultureinfo]::GetCultureInfo("en-US").NumberFormat.PositiveInfinitySymbol
提供 Infinity
,而不是 ∞
(当前文化是 en-US
)。结论:决定的是 Windows 版本,而不是 .NET 版本。【参考方案6】:
这与您的 Windows 10 区域设置有关。
在 Windows 10 Pro 版本 2004 上测试。我刚刚通过执行以下操作解决了它:
-
在开始时输入“区域设置”。
点击“其他日期、时间和区域设置”
点击“更改日期、时间或数字格式”
转到“管理”标签
点击“更改系统区域设置”
选中“测试版:使用 Unicode UTF-8 获得全球语言支持”复选框
重启你的电脑,现在你的 8 将打印为 ∞
【讨论】:
好招!除了 Windows 需要“重新启动”外,即使在打开 Visual Studio 的情况下,它也能立即工作。【参考方案7】:运行 .Net 4 及以上版本时,控制台会显示无穷大的“8”,否则之前的版本会显示“无穷大”。
使用 Console.OutputEncoding = Encoding.Unicode;在 .Net 4 及更高版本中将获得无穷大以显示为 ∞,但在以前的版本中会引发 IOException。
注意:我在 Windows 10 64 位上运行 Visual Studio 2015 社区版
【讨论】:
以上是关于为啥无穷大在 Windows 10 控制台中打印为“8”?的主要内容,如果未能解决你的问题,请参考以下文章