为什么这个显式演员的结果与隐式演员的结果不同?

Pau*_*ce. 12 c casting type-conversion

为什么这个显式演员的结果与隐式演员的结果不同?

#include <stdio.h>

double  a;
double  b;
double  c;

long    d;

double    e;

int main() {
    a = 1.0;
    b = 2.0;
    c = .1;

    d = (b - a + c) / c;
    printf("%li\n", d);        //    10

    e = (b - a + c) / c;
    d = (long) e;
    printf("%li\n", d);        //    11
    }
Run Code Online (Sandbox Code Playgroud)

如果我做d =(长)((b - a + c)/ c); 我也得到10.为什么双重赋值有所不同?

Jon*_*eet 16

我怀疑差异是从80位浮点值转换为长转换与从80位浮点值到64位浮点值的转换然后转换为长转换.

(80位出现的原因是,这是用于实际算术的典型精度,以及浮点寄存器的宽度.)

假设80位结果类似于10.999999999999999 - 从那里转换为长数10.但是,最接近的64位浮点值到80位值实际上是11.0,因此两阶段转换最终会产生11.

编辑:给这个更多的重量......

这是一个Java程序,它使用任意精度算法进行相同的计算.请注意,它将最接近0.1的double值转换为BigDecimal - 该值为0.1000000000000000055511151231257827021181583404541015625.(换句话说,无论如何,计算的确切结果不是 11.)

import java.math.*;

public class Test
{
    public static void main(String[] args)
    {
        BigDecimal c = new BigDecimal(0.1d);        
        BigDecimal a = new BigDecimal(1d);
        BigDecimal b = new BigDecimal(2d);

        BigDecimal result = b.subtract(a)
                             .add(c)
                             .divide(c, 40, RoundingMode.FLOOR);
        System.out.println(result);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是结果:

10.9999999999999994448884876874217606030632
Run Code Online (Sandbox Code Playgroud)

换句话说,这对于大约40个十进制数字是正确的(超过64或80位浮点数可以处理的方式).

现在,让我们考虑这个数字在二进制文件中的含义.我没有任何工具可以轻松地进行转换,但我们再次使用Java来提供帮助.假设标准化数字,"10"部分最终使用三位(比11位= 1011少一位).留下60位尾数用于扩展精度(80位)和48位用于双精度(64位).

那么,每个精度中最接近11的数字是多少?再次,让我们使用Java:

import java.math.*;

public class Test
{
    public static void main(String[] args)
    {
        BigDecimal half = new BigDecimal("0.5");        
        BigDecimal eleven = new BigDecimal(11);

        System.out.println(eleven.subtract(half.pow(60)));
        System.out.println(eleven.subtract(half.pow(48)));        
    }
}
Run Code Online (Sandbox Code Playgroud)

结果:

10.999999999999999999132638262011596452794037759304046630859375
10.999999999999996447286321199499070644378662109375
Run Code Online (Sandbox Code Playgroud)

所以,我们得到的三个数字是:

Correct value: 10.999999999999999444888487687421760603063...
11-2^(-60): 10.999999999999999999132638262011596452794037759304046630859375
11-2^(-48): 10.999999999999996447286321199499070644378662109375
Run Code Online (Sandbox Code Playgroud)

现在为每个精度计算出最接近正确值的值 - 为了扩展精度,它小于11.将每个值舍入为long,最后分别为10和11.

希望这足以说服怀疑者;)