次の質問をされたのですが、どう答えていいのかわかりませんでした。誰かが助けてくれるかどうか疑問に思っていました:
C# を使用し、Math 関数を使用しない場合 (Round() と Truncate() は使用できません)、次の double 3.009784654 を取得し、小数点以下 4 桁に丸めます。
これは、クラスのプロジェクトや宿題ではなく、面接のためでした。インタビュアーは私にモッドを使わせようとしているようだったが、私はまだそれを行う方法を思いつかなかった.
ありがとう!
切り捨てるには (丸め規則が指定されていないため): 1e4 で乗算し、int にキャストし、1e4 で除算します。
正しい結果のほとんどを表現できないため、期待されるツールを考えると、タスクは一般的に不可能であるため、これは悪いインタビューの質問です。つまり、一般的な浮動小数点型は、正しい数学的結果3.098を正確に表すことはできません。したがって、正解を計算して返すことは不可能です。別のタイプ(整数、文字列、10進浮動小数点形式などでスケーリング)で値を返すなど、別のメカニズムを使用する必要があります。
インタビュアーが期待していたかもしれない答えは、(int)(x * 10000 + .5)*。0001を評価することだと思います。これにより、目的の結果が整数になるように値がスケーリングされ(丸めクォンタム、.0001は1にスケーリングされます)、. 5が加算され、整数に切り捨てられ、スケーリングが逆になります。.5の加算と切り捨ての組み合わせは、xが正である必要があり、ゼロから離れて丸められ、範囲/ドメインの問題があることを除いて、丸めとほぼ同じです。それらの調整は、状況や望ましい動作に応じて行うことができます。そしてもちろん、正確な結果を表すことができないため、答えは一般的にわずかに正しくありません。
さらに興味深い答えは、(x * 10000 + 0x1p52-0x1p52)*。0001を評価することです。これにより、現在の浮動小数点丸めモードを使用して値がスケーリングされ、整数に丸められ、スケーリングが元に戻されます。一般的なdouble型の仮数は53ビットであるため、丸めが行われます。したがって、上位ビットの値が0x1p52(2 52)の場合、下位ビットの値は0x1p0(2 0 )になります。、1)とも呼ばれます。0x1p52を加算した結果を生成するには、仮数を丸める必要があります。これは、浮動小数点ハードウェアで自動的に行われます。次に、0x1p52を引くと、追加された数値が削除され、丸められた値が残ります。以前と同様に、範囲/ドメインに関する警告があり、コンパイラーが倍精度演算を実行し、それ以上のものではないことを確認し、調整を行うことができます。ただし、一部のハードウェアでは、整数に変換して戻すよりも高速です。
fmodまたは文字列変換を使用すると、除算が必要になるためパフォーマンスが低下します。これは、ほとんどの一般的なプロセッサでは低速です。
本当にmodが必要な場合は、次のことができます。
double number = 3.009784654;
double truncatedNumber = number - number % 0.0001;
Comma の後に 10^numberOfDigits を掛け、int に変換してから float に戻し、10^ で割ります...
double x = 3.009784654;
x = ((double)((int)(x * 10000))) / 10000;
modを使用した回答:
double d = 1.23456789;
int digitsToKeep = 2;
double divisor = Math.Pow(10, digitsToKeep * -1);
double rounded = d - (d % divisor);