将浮点数舍入到预定义点的常规网格

Ste*_*veL 27 c++ rounding

我想将浮点数舍入到给定的精度,例如:

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
Run Code Online (Sandbox Code Playgroud)

我无法更好地解释它,但其原因是将点位置(如0.131f,0.432f)转换为网格中瓷砖的位置(如0.1f,0.4f).

mar*_*n78 25

只要您的网格是常规的,只需找到从整数到此网格的转换.那么让我们说你的网格是

0.2  0.4  0.6  ...
Run Code Online (Sandbox Code Playgroud)

然后你绕过

float round(float f)
{
    return floor(f * 5 + 0.5) / 5;
    // return std::round(f * 5) / 5; // C++11
}
Run Code Online (Sandbox Code Playgroud)

  • @Niki ...而这正是您所期望的,不是吗? (2认同)
  • 什么条件 如我所写,“假设您的网格为0.2 0.4 0.6 ...” (2认同)

Nim*_*Nim 8

标准ceil(),floor()函数没有精度,我想可以通过添加自己的精度来解决这个问题 - 但这可能会引入错误 - 例如

double ceil(double v, int p)
{
  v *= pow(10, p);
  v = ceil(v);
  v /= pow(10, p);
}
Run Code Online (Sandbox Code Playgroud)

我想你可以测试看看这对你来说是否可靠?


sla*_*ais 6

您可以使用的算法:

  • 获得10次幂(有效位数)(= P10)
  • 将您的双倍乘以P10
  • 加:0.5(如果是负数则减去 - 见Ankush Shah的评论)
  • 将此总和的整数部分除以(P10) - 答案将是您的四舍五入的数字

  • 小点:如果数字为负数,则必须减去0.5 (2认同)

eac*_*eau 5

编辑1:我在python中寻找numpy的解决方案,并没有意识到OP要求C++哈哈,哦.

编辑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
Run Code Online (Sandbox Code Playgroud)

这里也是一个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;
}
Run Code Online (Sandbox Code Playgroud)

输出:

0.1
0
0.6
0.5

0.1
0
1
1

1.23
1.03e+06
0.00923
Run Code Online (Sandbox Code Playgroud)