Casting是解释价值还是仅仅是比特?

时间:2014-07-23 02:43:49

标签: c# casting double long-integer

所以我总是理解,铸造意味着取一些东西,并将其解释为铸造实体(必要时截断)。但是我在C#中注意到,你可以采用一个双精度,这是一个包含指数和值的64位表示。您可以将其强制转换为long,这是一个没有指数的整数的64位表示。因此,在我看来,如果你把一个随机的十进制值(比如说10.43245)存储在一个double中,然后将它转换为long,你会得到一些随机数,恰好是那个二进制文件在长。然而,这不是发生的情况,您只需获得截断的十进制值和值10。

我对铸造的定义是错误的吗?或者c#在这里稍微弯曲一下规则,以便给程序员更多的东西以及他们对这种演员的期望(我也假设java也可以这样做,c ++怎么样?)

6 个答案:

答案 0 :(得分:2)

在c#cast is an explicit conversion中。 C#规范5.0的第6节涉及转换。特别是第6.2.1节介绍了如何在语言中定义数值显式转换。作为一项规则,他们试图保留尽可能多的转换数值。

答案 1 :(得分:2)

来自MSDN

  

从double或float值转换为整数类型时,该值将被截断。如果结果积分值超出目标值的范围,则结果取决于溢出检查上下文。在已检查的上下文中,抛出了OverflowException,而在未经检查的上下文中,结果是未指定的目标类型值。

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

答案 2 :(得分:2)

转换的想法是通过所述转换将数据转换为另一种类型,几乎没有数据丢失。要完全具备技术性,我们将引用Casting and Type Conversions页面:

  

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

我们将重点关注“没有数据丢失。”

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

按照您的示例,double 10.43245投射到long,我们面临一个案例,无论如何,都存在类型隐式数据丢失:10.43245 10,也不是随机的数字串。 double将在小数点后存储更多位数(特别是因为long存储实数为零),因此无论如何转换此数字都会导致数据丢失。

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

因此,在接受我们面临数据丢失的事实之后,必须选择最有意义的方法来丢失数据。我们可以通过保留位顺序以及所有这些来获取它的随机字符串,或者我们可以以原始的二进制形式丢失它并保留“数字的“我们可以,在这种情况下,就是:10楼。

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

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

答案 3 :(得分:2)

没有什么神奇之处,但它必须做的不仅仅是直接转换位。例如,看一下如何将float转换为汇编中的整数:

[参考:http://www.codeproject.com/Articles/10679/Convert-Float-to-Int-using-Assembly-Language-Progr]

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

它正在转移,然后修剪,然后减去,然后再转移。

答案 4 :(得分:1)

Casting会截断double。你要找的是C#中的BitConverter.DoubleToInt64Bits或Java中的Double.doubleToLongBits

答案 5 :(得分:1)

long x = (long) doubleVal;

是显式转换的示例,并将尝试保留数值。

如果您更喜欢操纵双精度位,可以使用不安全的代码进行自我转换:

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

或使用库函数BitConverter.DoubleToInt64Bits