3

100 分の 1 を超えるすべてを切り捨てようとしています。(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;
    }

前もって感謝します!!!!PSフォーマットについて申し訳ありません私はまだstackoverflowに慣れています

キー フレーズ: double から int への変換 精度エラー

4

3 に答える 3

5

浮動小数点の精度エラーに苦しんでいると思います。

次のようにして、これを修正できるはずです。

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

別の方法は、入力時にこれが発生しないようにすることです。double で読み取る代わりに、文字列を読み取り、それを解析してドルとセントの金額を取得します (セントは、小数点以下があれば正確に 2 桁です)。その後、他のすべてを無視できます。

一般に、セント単位で切り捨てられた金額を扱う場合は、セント単位で整数を使用するのが最善の方法です。それか、切り捨てではなく丸めます (上記の例では、0.5 のイプシロンを意味します)。

于 2012-09-17T04:49:17.853 に答える
3

フロートはバイナリで次のように表されることを理解する必要があります。

2^(指数) * 仮数部

指数は標準の整数ですが、仮数 (1 ~ 2 の値) はビット数で、各ビットは分数を表します: 1、1/2、1/4、1/8、1/16 など。 . したがって、仮数が特定の値を正確に表すことは不可能であり、+/- 数分の 1 の精度になります。

たとえば、あなたは 33.30 に言及しました。float として 33.30 は 2^5 * 仮数のみです。

この場合、仮数は正確に 33.30/32 = 1.40625 でなければなりません。しかし、分数からそれを作ることで、最も近いものは次のようになります: 1.0406249999999999111821580299874767661094. したがって、double の実際の値は 33.30 ではなく、その 33.29999999999999971578290569595992565155029296875 であり、整数への型キャストを行うと、もちろん 33.29 に丸められます。

プログラムを修正する正しい方法は、そもそもフロートをスキャンしないことです。10 進数で区切られた 2 つの整数をスキャンする必要があります。scanf が 2 つの整数をスキャンしなかったことを示す値を返した場合は、ドルのみの値の場合は 1 つの整数としてスキャンします。

悲しいことに、printf は内部の int への変換によって機能し、小数点以下 6 桁を超える倍精度浮動小数点数を適切に出力しません。

于 2012-09-17T12:00:06.770 に答える
1

ほとんどのマシンは、10 進浮動小数点ではなく、2 進浮動小数点を使用します。2 進数から 10 進数への変換では (理論上) 常に正確な値が得られますが、丸めを行わずに 10 進数から 2 進数に変換することは不可能です (数値の桁数が無限にあるという非現実的なケースは考慮していません)。

そのため、すべての 2 進浮動小数点数は、10 進数の数値からわずかにずれます。

2 進数で表すことができる 1 桁の小数は、.0、.5 のみです。

同様に、2 進数で正確に表現できる 2 桁の小数は、.00、.25、.50、.75 です (こちらを参照)。

必要に応じて、4 分の 1 に最も近い端数に丸めることができます。

于 2012-09-17T08:28:12.503 に答える