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

2024-04-14

是否有任何 C# 规范说明如何隐式转换整型类型的项(例如,int) 的条款double应该可以工作吗?如果是这样,有人可以告诉我算法或指导我吗?

C# 6.0 规范草案 https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/lexical-structure在词法结构 -> 语法 -> 词法语法 -> 词法分析 -> 标记 -> 文字 -> 实数下指出“float 或 double 类型的实数文字的值是通过使用 IEEE‘舍入到最近’模式来确定的” ;但是我无法找到有关隐式转换如何工作的任何信息。

我在同一规范中的“转换”->“隐式转换”->“隐式数字转换”下发现的唯一内容是“从int, uint, long, or ulong to float和来自long or ulong to double可能会导致精度损失,但永远不会导致幅度损失。”

I do know that implicit conversions don’t follow the same algorithm that real literals do as the below program illustrates*:

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];
        }
    }
}

Edit

上面的代码可能比它需要的更“复杂”。这是另一个程序,希望能够澄清我的问题。

using System;
using System.Diagnostics;
namespace App
{
    internal static class Program
    {
        internal static void Main()
        {
            Debug.Assert(10648738977740919977 != 10648738977740919977d);
        }
    }
}

Addendum

正如 The General 和 mjwills 在评论中所述,这几乎肯定是由于 x86 等某些 ISA 提供的扩展精度格式造成的。至于为什么.NET Core编译器依赖扩展格式来转换ulong to a double但对于真正的文字却没有做同样的事情超出了我的范围。不确定这在技术上是否是一个“错误”,但如果两者都做了同样的事情那就太好了。由于 IEEE 754-2019 明确允许超过 64 位的精度,因此可以符合上述规范并仍然使用扩展格式。无论如何,ulongvalue 可以完全适合 x86 扩展格式的 64 位有效数,因此不会进行舍入。

TL;DR(又名编辑 2)

我将以这样一个事实作为序言:我从根本上和哲学上反对我将要写的内容是必要的甚至是可取的这一观念。我相信像这样的特定编程语言特有的技术问题仍然“适合”Stack Overflow,而不是任何其他 Stack Exchange 网站(例如,计算机科学、理论计算机科学、数学和 Math Overflow,例如同伦之类的问题)类型理论)。这意味着想要了解某件事的实质细节——即使人们可能(错误地)认为这些事情会导致违反“最佳实践”——仍然是一个值得提出的问题。如果存在更根本的问题,那么可以提出一个单独的问题。

背景

我正在创建一个 128 位无符号整数类型,U128,在我的工作中,我们使用 VB.NET 进行编写。我决定实现显式强制转换的功能U128条款Double (i.e., double用 C# 术语来说)。 IEEE 754 二进制 64 和二进制 32 是相当简单的格式,因为它们几乎与以 10 为基数的实数的格式相同 - 当然它们必须制成有限的位序列并具有有偏差的指数。不管怎样,我首先在 Rust 中实现了它,因为 Rust 有一个原生的 128 位无符号整数类型,u128; Rustonomicon 明确说明了如何从u128条款f64条款行为。这让我可以用 Rust 的算法来测试我的算法;毫不奇怪,由于该算法的琐碎性质(大约 12 行代码),我的实现在几个边缘情况和 10 亿个随机生成的数字上与 Rust 的实现相匹配 - 不,我没有花时间正式验证我的算法是否正确。

然后,我将我的算法移植到 VB.NET,因为我知道 C# 在这里更受欢迎,所以我也用 C# 重写了它,并确认它具有相同的行为,但我想确信在翻译过程中不会丢失任何内容。我能做的最好的事情就是比较演员阵容ULong (ulong在 C# 中)术语Double具有等价强制转换的术语ULongs as U128s to Doubles。果然,当我发现时我很沮丧10648738977740919977UL与同等产品的铸造方式不同U128。我(正确地)假设舍入存在问题 — 仅供参考,C# 规范没有说明如何对完全位于两个数字之间的数字进行舍入;但正如预期的那样,它四舍五入到偶数。当我比较第一个字节时(我使用的是小端 CPU)Double当我的演员阵容与 Rust 的演员阵容创建时,我发现我的演员阵容是正确的。此时,我认为 VB.NET 有一些“可疑”的地方(后来在 C# 中得到了证实),因为我通常更信任 Rust,并且如前所述,该算法相当简单。

幸运的是,我当时not意识到 C# 允许程序在具有扩展精度功能的 CPU 上使用扩展精度功能的(不幸的)怪癖包括不合规的 CPU,例如仅具有 80 位精度的基于 x86 的 CPU。如果我知道这一点,我可能会放弃它。

直到我检查了第一个字节Double term, 10648738977740919977R (10648738977740919977d在 C# 中),我真的很困惑,因为我发现它did同意我的算法。怎么会这样?我使用了相同的机器,使用相同的编译器针对相同的平台进行编译。最后,我正确地推测词法解析器处理真实文字的方式与处理转换为整数文字的方式可能存在行为差异Doubles。为了测试这个理论,我在最初的帖子中修改了程序(当时使用的是 VB.NET)。

此时,我假设隐式转换使用了一种不同的算法(可能是出于效率原因,因为必须跟踪 3 个附加位才能知道如何正确舍入)。That这就是为什么我的问题是这样提出的。我想知道算法这样我的算法就会与它保持一致(即使我的初始算法(很可能)在技术上按照 IEEE 754 是正确的)。

幸运的是,在 mjwills、The General 和 NetMage 最终的帮助下,我们发现这很可能是由于我的 CPU 的扩展精度功能不合规所致;尽管事实上这发生在汇编时间与之前强调的帖子根本不同runtime差异。

我鼓励大家花时间阅读amazingtannergooding 在我最终发布的答案的链接中给出了答案和评论(包括花费 15 美元阅读有关何时可以使用扩展精度能力及其要求的正式证明)。

* Compiled with Microsoft Visual C# Compiler version 3.7.0-6.20459 for .NET Core 3.1 on Windows 10 Pro 18363.1139 on an Intel Core i7-6600U CPU.


该算法为 IEEE 754 舍入到最接近的值,并为偶数。问题中显示的“反例”实际上是已被接受的错误的证据Roslyn https://github.com/dotnet/csharplang/discussions/4074团队。该错误是由“运行时转换实现”引起的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# 如何将整型的项隐式转换为 double 的项? 的相关文章

  • 为什么通过派生类对基类的引用与 :: - 运算符不明确?

    所以我想知道为什么以下钻石问题的代码片段无法编译 我知道这个问题通常是通过虚拟继承来解决的 我不是故意使用它的 该代码只是为了展示我的问题 即为什么编译器称此不明确 因此 我在 struct Base 中声明了两个成员变量 因为这两个子类
  • C free() 是如何工作的? [复制]

    这个问题在这里已经有答案了 可能的重复 malloc 和 free 如何工作 https stackoverflow com questions 1119134 how malloc and free work include
  • 将 OpenCV Mat 转换为数组(可能是 NSArray)

    我的 C C 技能很生疏 OpenCV 的文档也相当晦涩难懂 有没有办法获得cv Mat data属性转换为数组 NSArray 我想将其序列化为 JSON 我知道我可以使用 FileStorage 实用程序转换为 YAML XML 但这不
  • 将下拉列表与字典绑定

    我将字典绑定到下拉列表 举例来说 我的字典中有以下项目 Test1 123 Test2 321 我希望下拉文本采用以下格式 Test1 Count 123 Test2 Count 321 我沿着以下路径走 但没有运气 MyDropDown
  • 带有运算符语法的错误消息,但不带有函数语法的错误消息

    为什么我在调用 unary 时收到错误消息 使用运算符语法 如果我用函数语法调用它就可以了 现场演示 https godbolt org z j7AbeQ template
  • C# 编译器数字文字

    有谁知道 C 编译器数字文字修饰符的完整列表 默认情况下 声明 0 使其成为 Int32 声明 0 0 使其成为 Double 我可以在末尾使用文字修饰符 f 来确保某些内容被视为 Single 例如像这样 var x 0 x is Int
  • 静态类与类的实例

    我有一个静态类 用于访问我的公共属性 整个应用程序的全局属性 和我在应用程序运行期间使用的方法 例如 我在静态类中设置了一些属性 并且在应用程序运行时我可以从属性中获取值 但我可以使用单例模式创建非静态类并以相同的方式使用它 问题 对于我的
  • 在 C++11 中移出 stdpriority_queue 的元素

    最小的工作示例 include
  • 在 C# 中何时使用 ArrayList 而不是 array[]?

    我经常使用一个ArrayList而不是 正常 array 当我使用时 我感觉好像我在作弊 或懒惰 ArrayList 什么时候可以使用ArrayList在数组上 数组是强类型的 并且可以很好地用作参数 如果您知道集合的长度并且它是固定的 则
  • 子目录中的头文件(例如 gtk/gtk.h 与 gtk-2.0/gtk/gtk.h)

    我正在尝试使用 GTK 构建一个 hello world 其中包括以下行 include
  • 时间:2019-03-17 标签:c++fstream并发访问

    如果从不同的进程 线程同时访问文件会发生什么 据我所知 没有锁定文件的标准方法 只有操作系统特定的功能 就我而言 文件将被经常读取而很少写入 现在如果A打开一个文件进行读取 ifstream 并开始读取块 和B打开相同的文件进行写入 ofs
  • Resharper:IEnumerable 的可能多重枚举

    我正在使用新的 Resharper 版本 6 在我的代码中的几个地方 它给一些文本加了下划线 并警告我可能存在IEnumerable 可能的多重枚举 我理解这意味着什么 并在适当的情况下采纳了建议 但在某些情况下 我不确定这实际上是一个大问
  • 为什么不能调用带有 auto& 参数的 const mutable lambda?

    include
  • C++ 到 C# 事件处理

    所以我有我的C WinForm 应用程序 我从中调用我的C CLI MFC dll图书馆 但也有一些events在我的 C 库上 甚至此事件也发生在该库的本机 非 CLI 部分 我需要从我的 C 应用程序调用一些代码 并获取一些有关此事件的
  • 如何使用 CSI.exe 脚本参数

    当你运行csi exe 安装了 Visual Studio 2015 update 2 您将得到以下语法 Microsoft R Visual C Interactive Compiler version 1 2 0 51106 Copyr
  • C# 中的 C/C++ 代码编译器

    在 C 中 我可以使用下面的代码编译 VB 和 C 代码 但无法编译 C C 代码 有什么办法可以做到这一点吗 C 编译器 public void Compile string ToCompile string Result null st
  • 无法在 C# 中为 EventArgs 分配使用派生类型的事件处理程序

    所以我有一个事件声明如下 public event EventHandler OnChangeDetected 然后我有以下处理程序被分配给该事件 myObject OnChangeDetected OnTableChanged 我的理解是
  • C 中使用 getrandom 实现随机浮点数

    我试图生成一个介于 0 和 1 之间的随机浮点数 无论是在 0 1 还是 0 1 对我来说都不重要 网上关于此的每个问题似乎都涉及rand 呼叫 播种time NULL 但我希望能够每秒多次调用我的程序 并每次都获得不同的随机数 这引导我找
  • 无法识别解决方案文件夹中的 Visual Studio 2017 Nuget.config

    我在使用 Visual Studio 2017 时遇到问题 新的解决方案不断引用 C Users yopa AppData Roaming NuGet Nuget config 中意外位置的 Nuget config 文件 我已将 nuge
  • 这种尺寸对齐是如何工作的

    对于所提供的评论 我无法理解以下代码 这段代码的作用是什么 以及等效的代码是什么8 aligned segment size must be 4 aligned attr gt options ssize 3 Here ssize is o

随机推荐

  • Ruby 最大整数

    我需要能够确定 Ruby 中的系统最大整数 有人知道怎么做吗 或者是否可能 FIXNUM MAX 2 0 size 8 2 1 FIXNUM MIN 2 0 size 8 2
  • 自动更新 .net 应用程序

    到目前为止 我已经在 net 中编写了 2 个相当大型的应用程序 它们都需要一个更新工具 以便在我推出新代码时自动更新应用程序 我发现 企业应用程序块更新程序 对于我的需求来说有点过于复杂 并且在发布时我发现 单击一次 令人沮丧 我发现的最
  • 错误:unpack_from 需要缓冲区

    我正在使用 struct 来格式化固定分隔的 txt 文件 这是前两行 Sat Jan 3 18 15 05 2009 62e907b15cbf27d5425399ebf6f0fb50ebb88f18 4a5e1e4baab89f3a325
  • 如何将图像路径和名称上传到数据库 - Codeigniter

    我知道这个问题已经被问过好几次了 但是我发现的所有其他问题都与我想要的不同 我想将文件名和文件路径上传到名为 工厂图像 的表 这样做的最佳方法是什么 我的控制器功能 function do upload config upload path
  • 这是 IOC 的典型用例吗?

    我当前的应用程序允许用户通过一组管理屏幕定义自定义 Web 表单 它本质上是一个 EAV 类型的应用程序 因此 我无法对 HTML 或 ASP NET 标记进行硬编码来呈现给定页面 相反 UI 从服务层请求 Form 对象的实例 服务层又使
  • ASP.Net:混合身份验证 Azure AD/表单

    我有一个使用表单身份验证的旧版 Asp Net MVC Razor WebApp 现在 由于某些用户拥有 Azure AD 帐户 因此我添加了一个特殊的 AD 登录按钮以及常用代码以使其正常工作 app UseOpenIdConnectAu
  • 茉莉花量角器打字稿在其块中发生预期故障后继续执行

    我正在使用 Protractor jasmine 框架和打字稿 所以我在describe中有多个it块 所以在每个it块内有很多方法或期望条件我正在验证 因此 当前当其中一个期望失败时 整个块就会终止 所以即使在一步失败后我也想继续执行 下
  • 主题/样式 Angular 2 可重用组件库

    一般问题 我想要设计可重用的 Angular 组件的样式以匹配特定客户端项目的样式 我在一个单独的项目中维护可重用组件 并从中生成一个 npm 包 该包被发布到私有 NPM 存储库 Sinopia 然后安装到多个客户端项目中 当然 一般样式
  • 从 ng-repeat 内部调用 angularjs 属性指令

    我有一个表列对象的集合 我正在使用 ng repeat 对其进行迭代 我正在根据用户想要查看的列动态构建表 每个 TH 标签都调用一个 可排序 指令 如下所示 th Heading th 当自定义属性的值被硬编码时 如上所述 这很好 但是
  • 确定 Any.Type 是否可选

    我正在尝试确定给定类型是否t Any Type 是一个可选类型 我正在使用这个测试 t is Optional
  • XAML 设计器未加载

    我正在尝试开发适用于 Windows 10 的通用应用程序 但 XAML 设计器无法加载 我尝试重新安装 Visual Studio 但似乎没有任何效果 Error System Runtime InteropServices COMExc
  • 如何强制 python 子图具有相等的宽度和单独的高度(gridspec 不起作用)?

    I have the following figure Equal aspect ratio for each of the axes is a requirement I d love the widths to match betwee
  • 将 JSON 时间戳字符串转换为 pandas dataframe 中的 python 日期

    我有一个从 JSON 读取的 pandas 数据框 其中一个日期列是一种奇怪的时间戳格式 如下所示 日期 1405961743000 0100 如何将整列转换为 python 日期 我已经能够使用 datetime 手动将该日期转换为 py
  • Android ToggleButton 自定义样式未应用

    我跟着这个例子 http www mokasocial com 2011 07 sexily styled toggle buttons for android 用于将一些自定义主题应用于我的切换按钮 但是当我运行我的应用程序时 我看到通用
  • 如何在 AWS API 调用中使用“NextToken”

    我遇到了一个小问题 我真的很难理解它是如何工作的 我正在编写一个工具 它基本上执行描述组织来收集我们的 AWS 组织中的所有帐户 根据文档here https boto3 readthedocs io en latest reference
  • 解决IContainer

    从应用程序的类内部获取 Autofac 容器的建议方法是什么 Autofac 是否提供解析类上的 IContainer 属性 或者在构建容器后是否需要全局存储该容器 你需要IComponentContext or ILifetimeScop
  • OpenCV 从相机捕获 YUYV,无需 RGB 转换

    我尝试使用 openCV c 从 LI USB30 V024 立体相机捕获左右图像 而不自动将其转换为 RGB 相机输出 YUYV 格式的图像 我尝试使用 videoCapture set CV CAP PROP CONVERT RGB f
  • 带有 *ngIf 内部的模板,更改模型后不起作用

    Problem Angular 2 2版本之后 我注意到我的应用程序的某些组件存在问题 即更新数据后 视图中的数据错误 它显示了正确大小的列表 但仅包含第一项的数据 示范 我创建这个 Plunker 有一个简单的例子 http plnkr
  • Chrome 屏幕截图仅在首先单击扩展程序时有效

    因此 我尝试编写一些代码 以便在按下我的网站上的按钮时可以截取页面的屏幕截图 代码可以工作 但唯一的问题是我必须先单击 chrome 扩展 然后才能单击按钮来截取屏幕截图 我猜这是因为活动选项卡未被调用 有任何想法吗 这是错误消息 运行 t
  • C# 如何将整型的项隐式转换为 double 的项?

    是否有任何 C 规范说明如何隐式转换整型类型的项 例如 int 的条款double应该可以工作吗 如果是这样 有人可以告诉我算法或指导我吗 C 6 0 规范草案 https learn microsoft com en us dotnet