为什么我只有1%的时间得到不同的结果?

时间:2012-09-17 04:35:36

标签: c casting int double formula

我试图截断超过百分之一十进制的所有内容。 (13.4396将是13.43)不是总是或从不工作?

我有这个99%的公式:

    input = (( (double) ((int)(orgInput * 100)) )  / 100) ;

然后我有这个算术等价的公式序列:

    input = (orgInput * 100);
    input = (int) input;
    input = (double) (input);
    input = input / 100;

这些输入未提供所需的结果(公式截断并向下舍入,而细分步骤输出所需的结果):

12.33

99.99

22.22

44.32

56.78

11.11

然后对我来说更大的一个谜团是为什么33.30对他们中的任何一个都不起作用。以下是我的程序,它不断运行以证明我的问题。

    #include <stdio.h>
    #include <stdlib.h>

    int main(void)
    {
        double orgInput, input;
        while (4!=3)
        {
            printf("Please enter the dollar amount (up to $100)  => ");
           scanf("%lf", &orgInput);

            /* Truncates anything past hundredths place */
            input = (orgInput * 100) ;
            printf("\n1. input is %g \n ", input);

            input = (int) input ;
            printf("\n2. input is %g \n ", input);

            input = (double) (input)   ;
            printf("\n3. input is %g \n", input);

            input = input / 100 ;
            printf("\n4. input is %.2lf \n", input);

            input = (( (double) ((int)(orgInput * 100)) )  / 100) ;
            printf("\nUsing the formula the input is %.2lf \n \n\n", input);

        }
        system("PAUSE");
        return 0;
    }

提前谢谢!!!!附:对不起格式化我仍然习惯stackoverflow

关键词: 双转换为int 精度错误

3 个答案:

答案 0 :(得分:5)

我认为您遇到了浮点精度错误。

您应该可以通过以下方式解决此问题:

const double epsilon = 1e-10;  // Or some suitable small number
input = floor(orgInput * 100 + epsilon) / 100;

另一种方法是在输入时阻止这种情况发生。你不是读取一个双字符串,而是读取一个字符串,然后解析它以获得美元和美分金额(如果有的话,分数正好是小数点后面的2位数)。然后你可以忽略其他一切。

一般情况下,如果您正在使用截断到美分的资金,您可能最好将其保留为美分并使用整数。无论是圆形还是圆形而不是截断(对于我上面的例子,这意味着epsilon为0.5)。

答案 1 :(得分:3)

您需要了解浮点数以二进制形式表示为:

  

2 ^(指数)*尾数

指数是一个标准整数,但是尾数(1到2之间的值)是一个位数,其中每个位代表一个分数:1,1 / 2,1 / 4,1 / 8,1 / 16等等因此...尾数不可能精确地表示某些值,它的准确度为+/-一些分数。

例如你提到了33.30。浮点数33.30只能是:2 ^ 5 *尾数。

在这种情况下,尾数必须精确为33.30 / 32 = 1.40625。但是,通过使其成为最接近的分数,可以是:1.0406249999999999111821580299874767661094。所以double的实际值不是33.30,它的33.2999999999999971578290569595992565155029296875,当你将类型转换为整数时,它当然会向下舍入为33.29。

修复程序的正确方法不是首先扫描浮点数。您应该扫描两个由十进制分隔的整数,如果scanf返回一个值,表明它没有扫描两个整数,那么对于只有美元值的情况,将其扫描为一个整数。

可悲的是,printf通过转换到它内部的int来工作,并且无法正确打印任何具有超过6位小数的双精度浮点数,这就是为什么你看到它为33.30,即使你要求printf打印a的值双

答案 2 :(得分:1)

大多数机器使用二进制,而不是十进制浮点。虽然二进制到十进制的转换总是给出精确的值(在理论上),但是如果不进行舍入,就不可能从十进制转换为二进制(我不考虑数字可以具有无限数字位数时的不切实际的情况)。

因此,你所有的二进制浮点数都会略微偏离它们的十进制数。

可以用二进制表示的唯一1位小数部分是:.0,.5。

同样,二进制精确表示的2位十进制小数分别为:.00,.25,.50,。75(见here)。

如果您愿意,我怀疑,您可以四舍五入到最接近的四分之一。