2016-05-10 8 views
1

大きな数の分割を含むいくつかの問題を解決しようとしていました。C++の整数整数部の天井

LL結果=(LL)はceil((ダブル)( - B)/ C)、a、b、cは、長い長い整数(LL)は:私は私が使用して間違った結果を得ている特定のシナリオにつまずきました。

#include <stdio.h>  /* printf */ 
#include <math.h>  /* ceil */ 
#define LL long long 

int main() 
{ 
    LL a= 10000000000000000; 
    LL aa = 10000000000000000-1; 
    LL aaa = 10000000000000000+1; 
    int b = 1; 
    int c = 1; 
    printf ("%Ld\n", (LL)ceil((double)(a-b)/c)); 
    printf ("%Ld\n", (LL)ceil((double)(aa-b)/c)); 
    printf ("%Ld\n", (LL)ceil((double)(aaa-b)/c)); 
    return 0; 
} 

Output: 
10000000000000000 
9999999999999998 
10000000000000000 

これは以上10^16に等しい整数に発生し始め、10
で割り切れる長い長の上限は約10^18です。
このエラーの原因は何ですか?

私はGCC 5.1をC++ 14モード(ideone.com上)で使用しています。

+0

どのプラットフォームとコンパイラを使用していますか? – TriskalJM

+0

私はIdeone(C++ 14)が使用するコンパイラを試しました。ここにコードへのリンクがあります:http://ideone.com/aT6nem – gautamk

+2

倍精度の精度は52ビット= 15桁です。 – stark

答えて

1

の大きさがの数値を格納することもできますが、doubleの標準実装では約15-16桁の精度しか維持できません。

浮動小数点の減算は、特に2つの数値がほぼ同じ大きさである場合に問題になる可能性があります。両方の入力が(例えば)50ビットであるが、最初の40ビットが同一であれば、それらは相殺され、その結果は約10ビットしかない。

まず、すべての計算をlong longで行いたい場合は、結果として必要なタイプです。次に、できるだけ減算を遅らせるために(a-b)/ca/c-b/cに並べ替えることを検討したいかもしれません。

(x + y-1)/y 

だから、あなたのケースで:

(a - b + c-1)/c 

負の取り扱いと

+0

JerryとStarkに感謝します。 – gautamk

0

あなたは両方の値が正であることがわかっている場合、あなたは純粋な整数(または長い長い)での切り上げを計算することができます数字は読者のための練習として残されています(あなたがしたいことを正確に決めるのは少し難しいかもしれませんが、あなたは通常それを必要としません)。

+0

ありがとうございます。後で、エラーを見つけた後、私はこれに移動します。 – gautamk