gpt4 book ai didi

c# - C# 如何将整数类型的项隐式转换为 double 项?

转载 作者:行者123 更新时间:2023-12-04 11:04:35 26 4
gpt4 key购买 nike

是否有任何 C# 规范说明如何将整数类型的项(例如 int)隐式转换为 double 的项应该工作?如果是这样,有人可以告诉我算法或指导我吗?
C# 6.0 draft specification在词法结构 -> 语法 -> 词法文法 -> 词法分析 -> 标记 -> 文字 -> 真实文字下声明“float 或 double 类型的实数的值是通过使用 IEEE '舍入到最近'模式确定的” ;但是我找不到任何关于隐式转换如何工作的信息。
我在同一规范中的转换 -> 隐式转换 -> 隐式数字转换下找到的唯一内容是“来自 int 的转换” , uint , long , 或 ulongfloat来自 longulongdouble可能会导致精度损失,但永远不会导致幅度损失。”
我确实知道隐式转换不遵循与真实文字相同的算法,如下面的程序所示*:

using System;
using System.Diagnostics;
namespace App
{
internal static class Program
{
internal static void Main()
{
Debug.Assert(GetFirstByte(10648738977740919977) != GetFirstByte(10648738977740919977d));
}
private static byte GetFirstByte(double val)
{
return BitConverter.GetBytes(val)[0];
}
}
}
编辑
上面的代码可能比它需要的更“复杂”。这是另一个程序,希望能澄清我在问什么。
using System;
using System.Diagnostics;
namespace App
{
internal static class Program
{
internal static void Main()
{
Debug.Assert(10648738977740919977 != 10648738977740919977d);
}
}
}
附录
正如 The General 和 mjwills 在评论中所述,这几乎可以肯定是由于 x86 等某些 ISA 提供的扩展精度格式。至于为什么.NET Core编译器依赖扩展格式来转换 ulongdouble但对真正的文字不做同样的事情超出了我的范围。不确定这在技术上是否是一个“错误”,但如果两者都做同样的事情会很好。可以符合上述规范并仍然使用扩展格式,因为 IEEE 754-2019 明确允许超过 64 位的精度。不管怎样, ulong value 可以完全适合 x86 扩展格式的 64 位有效数,因此不会四舍五入。
TL;DR(又名编辑 2)
我将以这样一个事实开始这个编辑,即我从根本上和哲学上反对我将要写的东西是必要的,甚至是可取的。我相信特定于特定编程语言的技术问题仍然“适合” Stack Overflow 而不是任何其他 Stack Exchange 站点(例如,计算机科学、理论计算机科学、数学和数学溢出——对于像同伦这样的事情类型理论)。这意味着想要了解某事的本质细节——即使人们可能(错误地)认为这些事情会导致违反“最佳实践”——仍然是一个有值(value)的问题。如果存在更基本的问题,则可以针对它提出一个单独的问题。
背景
我正在创建一个 128 位无符号整数类型, U128 ,在我用 VB.NET 编写的工作中。我决定实现显式转换 U128 的能力条款到 Double (即 C# 中的 double)术语。 IEEE 754 binary64 和 binary32 是相当简单的格式,因为它们几乎与基数为 10 的实数的格式相同——当然,它们必须被制成有限的位序列并具有偏置指数。无论如何,我首先在 Rust 中实现了它,因为 Rust 有一个原生的 128 位无符号整数类型, u128 ;并且 The Rustonomicon 明确说明了如何从 u128 进行转换条款到 f64条款行为。这让我可以用 Rust 测试我的算法;不出所料,由于算法的简单性——它大约有 12 行代码——我的实现与 Rust 的几个边缘情况和 10 亿个随机生成的数字相匹配——不,我没有花时间正式验证我的算法是正确的.
然后我将我的算法移植到 VB.NET——知道 C# 在这里有多流行,我也用 C# 重写它并确认它具有相同的行为——但我想确信在翻译中没有丢失任何东西。我能做的最好的事情就是比较 ULong 的类型转换。 ( ulong 在 C# 中)术语到 Double具有等价转换的术语 ULong s 为 U128转至 Double s。果然,我发现的时候惊呆了 10648738977740919977UL与同等的 U128 不同.我(正确地)假设舍入有问题——仅供引用,C# 规范没有说明如何舍入完全位于两个数字之间的数字;但正如预期的那样,它四舍五入到偶数。当我比较 Double 的第一个字节时——我使用的是小端 CPU我的 Actor 是用 Rust 的 Actor 创造的,我发现我的 Actor 是正确的。在这一点上,我认为 VB.NET 有一些“可疑”(后来在 C# 中得到证实),因为我通常更信任 Rust,而且如前所述,该算法相当简单。
幸运的是,我没有意识到 C# 允许程序在 CPU 上使用扩展精度功能的(不幸的)怪癖,包括不兼容的 CPU,例如基于 x86 的 CPU,只有 80 位精度。如果我知道这一点,我可能会放弃它。
直到我检查了 Double 的第一个字节术语, 10648738977740919977R ( 10648738977740919977d 在 C# 中),我真的很困惑,因为我发现它确实与我的算法一致。这怎么可能?我使用了相同的机器,使用相同的编译器为相同的平台编译。最后,我正确地推测,词法解析器处理实际文字的方式与处理转换为 Double 的整型文字的方式可能存在差异。 s。为了测试这个理论,我在最初的帖子中(当时在 VB.NET 中)修改了程序。
在这一点上,我假设隐式转换使用了不同的算法(可能是出于效率原因,因为必须跟踪 3 个额外的位才能知道如何正确舍入)。这就是为什么我的问题是这样表述的。我想知道算法,以便我的算法与它保持一致(即使我的初始算法(很可能)按照 IEEE 754 在技术上是正确的)。
幸运的是,最终在 mjwills、The General 和 NetMage 的帮助下,发现它可能与我的 CPU 不兼容的扩展精度能力有关;尽管这发生在编译时这一事实与之前强调运行时差异的帖子有着根本的不同。
我鼓励每个人花时间阅读我最终发布的答案链接中 tannergooding 的惊人答案和评论(包括支付 15 美元以阅读有关扩展精度能力何时可以使用以及此类要求的正式证明)。
* 使用 Microsoft Visual C# 编译器版本 3.7.0-6.20459 编译,适用于英特尔酷睿 i7-6600U CPU 上的 Windows 10 Pro 18363.1139 上的 .NET Core 3.1。

最佳答案

该算法是 IEEE 754 舍入到最近,连到偶数。问题中显示的“反例”实际上是 Roslyn 已接受的错误的证据。团队。该错误是由“运行时转换实现”引起的。

关于c# - C# 如何将整数类型的项隐式转换为 double 项?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64546440/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com