为什么要在sbyte中强制转换大的double值在C#中返回0?

问题描述 投票:0回答:1

我实际上是在未经检查的上下文中测试C#中的转换行为。就像文档中所说的那样,在未经检查的上下文中,强制转换总是成功的。但是有时,在特定情况下,从一种特定类型到另一种类型的转换会产生意外的结果。

例如,我测试了三个“ double to sbyte”转换:

var firstCast = (sbyte) -129.83297462979882752;          // Result : 127.
var secondCast = (sbyte) -65324678217.74282742874973267; // Result : 0.
var thirdCast = (sbyte) -65324678216.74282742874973267;  // Result : 0.

请注意,第二个和第三个两倍之间的差仅为1secondDouble - firstDouble = 1)。在这种情况下,对于任何“大”双精度值,强制转换的结果似乎始终为0

我的问题是:为什么第二次和第三次强制转换会导致0?我在C#文档中搜索了答案,但没有找到任何答案。

我使用.Net Framework 4.7.2测试了以上内容。

c# casting double .net-4.7.2 sbyte
1个回答
3
投票

根据C# language specification

对于从float或double到整数类型的转换,处理取决于发生转换的溢出检查上下文:

[不使用checkedunchecked运算符,默认情况下,不检查溢出检查上下文,因此我们来看:

在未检查的上下文中,转换总是成功,并且按如下进行。

  • 如果操作数的值为NaN或无穷大,则转换结果为目标类型的未指定值。

  • 否则,源操作数朝零舍入到最接近的整数值。如果此整数值在目标类型的范围内,则此值是转换的结果。

  • 否则,转换结果是目标类型的未指定值。

这里,值既不是NaN也不是无穷大。朝零取整时,它们不在sbyte的有效范围内,该范围为-128到127,因此最后一个项目符号点适用,这意味着这种转换的结果未指定。

换句话说,此强制转换的结果取决于您使用的编译器。不同的编译器可以做不同的事情,它们仍将被称为C#编译器。无论您使用的编译器是什么,都可能以为要转换的值离下/上限很远时,返回0进行转换是一个更好的主意。

© www.soinside.com 2019 - 2024. All rights reserved.