C++ 将浮点舍入到预定义点的规则栅格

C++ 将浮点舍入到预定义点的规则栅格,c++,rounding,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 我无法更好地解释它,但其原因是将点位置(如0.131f,0.432f)转换为网格中瓷砖的位置(如0.1f,0.4f)。标准的ceil(),floor()函数没有精度,我想你可以通过增

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

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)。

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

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

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

只要你的网格是规则的,只要找到一个从整数到这个网格的转换。假设你的网格是

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
}
使用
floor()
ceil()
floor
将浮点值转换为下一个较小的整数,
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。

可以使用以下算法:

  • 取10的幂(有效位数)(=P10)
  • 将双倍值乘以P10
  • 加:0.5(如果为负,则减去-见Ankush Shah的评论)
  • 将该总和的整数部分除以(P10)-答案将是您的整数

编辑1:我在Python中寻找NoMPY的解决方案,没有意识到OP问C++ HAHA,哦,好吧。 编辑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++标量版本,你可以使用类似的特征来做类似的事情(它们有逻辑索引):(我也把这个当作练习更多的刺激哈哈):


由于Mooing Duck编辑了我的问题并删除了表示问题不应包含答案(可以理解)的代码,因此我将在此处编写解决方案:

float round(float f,float prec)
{
    return (float) (floor(f*(1.0f/prec) + 0.5)/(1.0f/prec));
}

通常,您在编译时知道所需的精度。因此,使用可用的模板Pow函数,您可以执行以下操作:

template <int PRECISION>
float roundP(float f)
{
    const int temp = Pow<10,PRECISION>::result;
    return roundf(f*temp)/temp;
}

int main () {
    std::cout << std::setprecision(10);
    std::cout << roundP<0>(M_PI) << std::endl;
    std::cout << roundP<1>(M_PI) << std::endl;
    std::cout << roundP<2>(M_PI) << std::endl;
    std::cout << roundP<3>(M_PI) << std::endl;
    std::cout << roundP<4>(M_PI) << std::endl;
    std::cout << roundP<5>(M_PI) << std::endl;
    std::cout << roundP<6>(M_PI) << std::endl;
    std::cout << roundP<7>(M_PI) << std::endl;
}
模板
浮动圆整(浮动f)
{
const int temp=Pow::result;
返回圆f(f*温度)/温度;
}
int main(){

std::cout浮点数舍入算法:

 double Rounding(double src, int precision) {
         int_64 des;
         double tmp;
         double result;
         tmp = src * pow(10, precision);
         if(tmp < 0) {//negative double
            des = (int_64)(tmp - 0.5);
         }else {
            des = (int_64)(tmp + 0.5);
         }
         result = (double)((double)dst * pow(10, -precision));
         return result;
    }
双舍入(双src,整数精度){
国际64日;
双tmp;
双重结果;
tmp=src*pow(10,精度);
如果(tmp<0){//负双精度
des=(int_64)(tmp-0.5);
}否则{
des=(int_64)(tmp+0.5);
}
结果=(双精度)((双精度)dst*pow(10,-精度));
返回结果;
}

我将简要优化最后几个答案,首先将输入数字转换为双精度,以防止溢出。示例函数(不太漂亮,但工作正常):

#包括
//四舍五入浮点到n小数精度
浮动轮数(浮动数,整数)
{
double m=(num<0.0)?-1.0:1.0;//检查输入是否为负
双压水堆=功率(10,12月);
回流浮子(地板((双)个数*米*压水堆+0.5)/压水堆)*米;
}

您可以使用以下功能将数字四舍五入到所需的精度

double round(long double number, int precision) {
  int decimals = std::pow(10, precision);
  return (std::round(number * decimals)) / decimals;
}
检查下面的一些例子

1)

2)

3)

4)

此函数甚至适用于精度为9的数字

5)


我曾经写过一个小函数,它将
双精度
舍入到一个固定的精度(2个小数点-如
0.01
),而不需要包含

constexpr-double-simplyRounded(const-double-value)
{
返回(;
}   
…这可以使您的精度达到1位小数(如
0.1
),获取并返回
float
,如下所示:

constexpr float simplyRounded(const float值)
{
返回(;
}

不是吗/=pow(10,p)或*=pow(10,-p)?将浮点数舍入到小数点后1位或更多位没有多大意义;像
0.1
这样的数字不能用二进制浮点数精确表示。舍入可以在输出(到字符串或文件)时完成。我们在IT部门,我们试图用一行代码来表示现实世界的无限可能性,这里的一切都是有意义的。我在游戏中使用它作为无限滚动背景,精度损失其实并不重要。我已经测试过了,它似乎无法正常工作。如果你尝试对127进行四舍五入,它将返回128(我对f和返回类型使用的是double而不是float)。@BlunT,可能你没有理解函数的要点,你传递的精度是多少?如果你输入2,你将得到128,因为你将得到0,2,4,6,128130…(2作为一个增量),如果通过127.456且精度为0.01f,则会得到127.46,因为127.46最接近于0,0.01,0.02f…..127.45127.46127.47(增量为0.01)@SteveL在这种情况下你是正确的,因为函数取整到最近的对数,我使用2作为精度。尽管如此,我认为问题的标题可能会误导。在我看来,考虑到其他编程语言中的其他round实现,精度指的是小数位数。sm要点:如果这个数字是负数,你必须减去0.5,那么负浮点数呢
template <int PRECISION>
double roundP(double f)
{
    const int temp = Pow<10,PRECISION>::result;
    return round(f*temp)/temp;
}
 double Rounding(double src, int precision) {
         int_64 des;
         double tmp;
         double result;
         tmp = src * pow(10, precision);
         if(tmp < 0) {//negative double
            des = (int_64)(tmp - 0.5);
         }else {
            des = (int_64)(tmp + 0.5);
         }
         result = (double)((double)dst * pow(10, -precision));
         return result;
    }
#include <cmath>

// round float to n decimals precision
float round_n (float num, int dec)
{
    double m = (num < 0.0) ? -1.0 : 1.0;   // check if input is negative
    double pwr = pow(10, dec);
    return float(floor((double)num * m * pwr + 0.5) / pwr) * m;
}
double round(long double number, int precision) {
  int decimals = std::pow(10, precision);
  return (std::round(number * decimals)) / decimals;
}
round(5.252, 0)
returns => 5
round(5.252, 1)
returns => 5.3
round(5.252, 2)
returns => 5.25
round(5.252, 3)
returns => 5.252
round(5.1234500015, 9)
returns => 5.123450002