31

浮動小数点数を指定された精度に丸めたいのですが、次に例を示します。

0.051 i want to convert it to
0.1

0.049 i want to convert it to
0.0

0.56 i want to convert it to
0.6

0.54 i want to convert it to
0.5

これ以上説明することはできませんが、これは、ポイントの位置(0.131f、0.432fなど)をグリッド内のタイルの位置(0.1f、0.4fなど)に変換するためです。

4

11 に答える 11

25

グリッドが規則的である限り、整数からこのグリッドへの変換を見つけるだけです。だからあなたのグリッドが

0.2  0.4  0.6  ...

それからあなたは丸めます

float round(float f)
{
    return floor(f * 5 + 0.5) / 5;
    // return std::round(f * 5) / 5; // C++11
}
于 2012-06-26T14:05:13.957 に答える
9

標準ceil()の ,floor()関数には精度がありません。独自の精度を追加することで回避できると思いますが、これによりエラーが発生する可能性があります-たとえば

double ceil(double v, int p)
{
  v *= pow(10, p);
  v = ceil(v);
  v /= pow(10, p);
}

これがあなたにとって信頼できるかどうかをテストすることができると思いますか?

于 2012-06-26T14:03:21.450 に答える
6

EDIT 1: Python で numpy のソリューションを探していましたが、OP が C++ を要求していることに気づきませんでした。

EDIT 2:笑、私はあなたの元の質問にさえ対処していないようです。精度(操作は数値に依存します)ではなく、小数(操作は指定された数値に依存しません)に従って四捨五入したいようです。他の人はすでにそれに対処しています。

私も実際にこれを探していましたが、何かを見つけることができなかったので、numpy 配列の実装をまとめました。slashmais が述べたロジックを実装しているようです。

def pround(x, precision = 5):
    temp = array(x)
    ignore = (temp == 0.)
    use = logical_not(ignore)
    ex = floor(log10(abs(temp[use]))) - precision + 1
    div = 10**ex
    temp[use] = floor(temp[use] / div + 0.5) * div
    return temp

これはC++スカラーバージョンでもあり、おそらくEigenを使用して上記と同様のことを行うことができます(論理インデックスがあります):(私はこれをさらにブーストハハを練習する機会としても取りました):

#include <cmath>
#include <iostream>
#include <vector>
#include <boost/foreach.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>

using namespace std;

double pround(double x, int precision)
{
    if (x == 0.)
        return x;
    int ex = floor(log10(abs(x))) - precision + 1;
    double div = pow(10, ex);
    return floor(x / div + 0.5) * div;
}

    template<typename T>
vector<T>& operator<<(vector<T> &x, const T &item)
{
    x.push_back(item);
    return x;
}

int main()
{
    vector<double> list;
    list << 0.051 << 0.049 << 0.56 << 0.54;
    // What the OP was wanting
    BOOST_FOREACH(double x, list)
    {
        cout << floor(x * 10 + 0.5) / 10 << "\n";
    }

    cout << "\n";

    BOOST_FOREACH(double x, list)
    {
        cout << pround(x, 0) << "\n";
    }

    cout << "\n";

    boost::function<double(double)> rounder = boost::bind(&pround, _1, 3);
    vector<double> newList;
    newList << 1.2345 << 1034324.23 << 0.0092320985;
    BOOST_FOREACH(double x, newList)
    {
        cout << rounder(x) << "\n";
    }

    return 0;
}

出力:

0.1
0
0.6
0.5

0.1
0
1
1

1.23
1.03e+06
0.00923
于 2012-10-14T15:41:56.893 に答える
6

使用できるアルゴリズム:

  • 10のべき乗(有効桁数)を取得 (=P10)
  • double 値に P10 を掛けます
  • 追加: 0.5 (または負の場合は減算 - Ankush Shah のコメントを参照)
  • この合計の整数部分を (P10) で割ります - 答えは四捨五入された数値になります
于 2012-06-26T14:08:18.857 に答える
4

とを使用floor()ceil()ます。floorfloat を次に小さい整数に変換ceilし、次に大きい整数に変換します。

floor( 4.5 ); // returns 4.0
ceil( 4.5 );  // returns 5.0

私は次のことがうまくいくと思います:

float round( float f )
{   
    return floor((f * 10 ) + 0.5) / 10;
}

floor( f + 0.5 )整数に丸めます。最初に 10 を掛けてから結果を 10 で割ることで、0.1 単位で丸めます。

于 2012-06-26T14:06:59.680 に答える
0

Mooing Duck が私の質問を編集し、質問に回答を含めてはならないというコードを削除したので (理解できる)、ここに解決策を書きます。

float round(float f,float prec)
{
    return (float) (floor(f*(1.0f/prec) + 0.5)/(1.0f/prec));
}
于 2015-03-17T05:25:02.373 に答える