C# 铸造是解释值还是仅解释位?

C# 铸造是解释值还是仅解释位?,c#,casting,double,long-integer,C#,Casting,Double,Long Integer,所以我一直理解强制转换意味着获取某事物的二进制,并将其解释为强制转换实体(必要时截断)。但是我注意到在C#中,可以使用double,它是一种64位表示,包括指数和值。您可以将其强制转换为long,这是不带指数的64位整数表示形式。因此,在我看来,如果你取一个存储在double中的随机十进制值(比如10.43245),并将其转换为long,你会得到一个随机数,这个随机数恰好是long中的二进制数。然而,情况并非如此,您只需得到截断的十进制数和10的值 我对铸造的定义是错误的吗?或者C++在这里稍微

所以我一直理解强制转换意味着获取某事物的二进制,并将其解释为强制转换实体(必要时截断)。但是我注意到在C#中,可以使用double,它是一种64位表示,包括指数和值。您可以将其强制转换为long,这是不带指数的64位整数表示形式。因此,在我看来,如果你取一个存储在double中的随机十进制值(比如10.43245),并将其转换为long,你会得到一个随机数,这个随机数恰好是long中的二进制数。然而,情况并非如此,您只需得到截断的十进制数和10的值


我对铸造的定义是错误的吗?或者C++在这里稍微弯曲了一些规则,给程序员更多的期望,他们可能会从这样的一个演员(我也假设java可能做同样的事情,C++)?C#规范5.0第6节涉及转换。特别是第6.2.1节介绍了如何在语言中定义数值显式转换。通常,他们会尽可能多地保留被转换的数值。

强制转换会截断双精度。您需要的是C#或Java。

来源:

从双精度值或浮点值转换为整数类型时,该值将被截断。如果生成的整数值超出目标值的范围,则结果取决于溢出检查上下文。在选中的上下文中,会引发OverflowException,而在未选中的上下文中,结果是目标类型的未指定值


因此,正如您所观察到的,当您将一个
double
转换为
long
这是一个整数类型时,您将得到截断的值。

转换的思想是通过所述转换将数据转换为另一种类型,几乎没有数据丢失。出于技术考虑,我们将引用以下页面:

隐式转换:不需要特殊语法,因为转换是类型安全的,不会丢失任何数据。示例包括从较小的整数类型到较大的整数类型的转换,以及从派生类到基类的转换

这里我们将重点讨论“不会丢失任何数据”

我认为您在这里面临的问题是转换发生在哪里,更重要的是,我们希望避免数据丢失

按照您的示例,将
double
10.43245转换为
long
,我们将面临这样一种情况,即无论发生什么,都存在一种类型的隐式数据丢失:10.43245不是10,也不是您的随机数字串
double
将在小数点后存储更多的数字(特别是因为
long
存储的是一个实零),因此,无论怎样,转换这个数字都会导致数据丢失

顺便说一句,这有点像把说出来的话转换成摩尔斯电码。我们这样做是因为它很有用。但在这个过程中,我们仍然失去了一些有价值的语言品质。这是一种折衷,我们选择支持数据传输的重要性,而不是以自然和情感的方式传达讲话的重要性

因此,在我们面临数据丢失这一事实被接受之后,我们必须选择在哪里丢失数据最有意义。我们可以以人类可读的形式丢失它,通过保留位顺序和所有这些,这就是你得到随机数字串的地方,或者我们可以以原始的二进制形式丢失它,并尽可能地保留“尽可能多的数字”,在本例中,这就是地板:10

本质上,这只是第一批语言建立时所做的另一个简单的权衡,没有人想改变一件好事。让
(long)10.43245
解析为
10
更有用

同样重要的是要记住,正如其他几位所指出的,这只是默认行为。因为这种类型转换存在,所以没有理由假设您不能将直接二进制值从一种类型转换为另一种类型。有许多语言中的方法,比如.NET,可以进行这种一对一位的转换。作为一个典型的用例,它是没有意义的,而语言设计,特别是对于我们主要处理的高级语言,是一个使典型用例尽可能高效和有效的问题

long x = (long) doubleVal;
是显式转换的示例,将尝试保留数值

如果您希望操纵double的位,您可以使用不安全的代码进行转换:

long x;
unsafe
{
    x = *((long*) &val);
}

或者使用库函数BitConverter.doubleToInt64位

它并没有什么神奇之处,但它必须做的不仅仅是位的直接转换。例如,看看您的程序集如何将浮点转换为整数:

[参考:


它是移动的,然后是修剪,然后减去,然后再移位。< / P>是,你的铸造定义是错误的。在C++ 10.43245中,也将被铸造成10。相关的:C++是说明性的,你有各种各样的演员来覆盖不同的场景。<代码> RealTytRask> <代码>意味着保留这些位,但是<代码> StistalCase< <代码>意味着应用。适当的转换。有关正确的答案,请参阅:

int ftoi(float flt)
{
    int i;
    _asm
    {
        mov  eax,flt; //loaded mem to acc
        rcl  eax,1;   //left shift acc to remove the sign
        mov  ebx,eax; //save the acc
        mov  edx,4278190080; //clear reg edx;
        and  eax,edx; //and acc to retrieve the exponent
        shr  eax,24;
        sub  eax,7fh; //subtract 7fh(127) to get the actual power 
        mov  edx,eax; //save acc val power
        mov  eax,ebx; //retrieve from ebx
        rcl  eax,8;     //trim the left 8 bits that contain the power
        mov  ebx,eax; //store
        mov  ecx, 1fh; //subtract 17 h
        sub  ecx,edx; 
        mov  edx,00000000h;
        cmp  ecx,0;
        je   loop2;
        shr  eax,1;
        or   eax,80000000h;        
loop1:    
        shr  eax,1; //shift (total bits - power bits);
        sub  ecx,1;
        add  edx,1;
        cmp  ecx,0;
        ja   loop1;
loop2:  
        mov  i, eax;        

//check sign +/-        
sign:
        mov  eax,flt;
        and  eax,80000000h;
        cmp  eax,80000000h;
        je     putsign;
    }

    return i;

putsign:
    return -i;
}