5

c/c++ を使用して、大きな倍精度数 (>1e6) を最も近いがより大きな浮動小数点数に丸めたいと考えています。私はこれを試しましたが、それが常に正しいかどうかはわかりません。それを行うための最速の方法があるかもしれません:

int main() {
    // x is the double we want to round
    double x = 100000000005.0;
    double y = log10(x) - 7.0;
    float a = pow(10.0, y);
    float b = (float)x;

    //c the closest round up float
    float c = a + b;
    printf("%.12f %.12f %.12f\n", c, b, x);
    return 0;
}

ありがとうございました。

4

3 に答える 3

6

double を float に割り当てて戻すだけで、float が大きいかどうかがわかります。そうでない場合は、float を 1 単位だけインクリメントする必要があります。(正のフロートの場合)。それでも期待どおりの結果が得られない場合は、double が float でサポートされているサイズよりも大きいため、float を Inf に割り当てる必要があります。

float next(double a) {
    float b=a;
    if ((double)b > a) return b;
    return std::nextafter(b, std::numeric_limits<float>::infinity());
}

[ハック] next_after の C バージョン (一部のアーキテクチャでは)

float next_after(float a) {
    *(int*)&a += a < 0 ? -1 : 1;
    return a;
}

それを行うより良い方法は次のとおりです。

float next_after(float a) {
   union { float a; int b; } c = { .a = a };
   c.b += a < 0 ? -1 : 1;
   return c.a;
}

これらの自作のハックは両方とも、Infs と NaN を無視します (そして、非負の float でのみ機能します)。数学は、float のバイナリ表現が順序付けられているという事実に基づいています。次の表現可能な float に到達するには、単純にバイナリ表現を 1 つ増やします。

于 2013-03-08T13:00:56.043 に答える
4

を使用する場合は、 nextafterf 関数を使用できます。

#include <stdio.h>
#include <math.h>
#include <float.h>

int main(){
  // x is the double we want to round
  double x=100000000005.0;

  float c = x;

  if ((double)c <= x)
    c = nextafterf(c, FLT_MAX);

  //c the closest round up float
  printf("%.12f %.12f\n",c,x);
  return 0;
}
于 2013-03-08T13:02:27.893 に答える
3

nextafterCには、ここで役立つ素晴らしい機能があります。

float toBiggerFloat( const double a ) {
    const float test = (float) a;
    return ((double) test < a) ? nextafterf( test, INFINITY ) : test;
}

数値のすべてのクラス (正/負、正規/非正規、無限、nan、 -0 ) でそれを示すテスト スクリプトを次に示します。

于 2013-03-08T13:04:48.257 に答える