我需要一个简单的浮点四舍五入功能,从而:

double round(double);

round(0.1) = 0
round(-0.1) = 0
round(-0.9) = -1

我可以找到 ceil()floor() 在数学。h-但不是 round().

它是存在的标准C++库的另一个名称下,还是失踪了吗?

有帮助吗?

解决方案

有在C ++ 98标准库无轮()。你可以自己写,虽然一个。以下是轮半向上的实现:

double round(double d)
{
  return floor(d + 0.5);
}

在可能的原因有在C ++ 98标准库中没有循环函数是,它实际上可以以不同的方式来实现。以上是一个常用的方法,但也有其他如舍入到甚至,该不太偏,而且如果你打算做了很多四舍五入的一般都比较好;这是一个有点复杂,以实现虽然

其他提示

提高提供一套简单的四舍五入的功能。

#include <boost/math/special_functions/round.hpp>

double a = boost::math::round(1.5); // Yields 2.0
int b = boost::math::iround(1.5); // Yields 2 as an integer

更多信息,请参阅 提高文件.

编辑:由于用C++11,还有 std::round, std::lround, , std::llround.

C++03标准的依赖C90标准,对于什么样的标准要求的 Standard C Library 这是复盖草案中的C++03标准(最近公开提供的标准草案C++03N1804)部分 1.2 规范性参考文献:

该图书馆所描述的,在第7条的ISO/IEC9899:1990年和第7条的 ISO/IEC9899/Amd。1:1995年以下称为标准的C 图书馆。1)

如果我们去的 C文件轮,lround,llround在cppreference 我们可以看到, 和相关职能的一部分 C99 因此不可用C++03或之前。

C++11这一变化由于用C++11依赖于C99草案的标准 C标准图书馆 因此提供了 std::轮和为整体回归类型std::lround、性传染疾病::llround :

#include <iostream>
#include <cmath>

int main()
{
    std::cout << std::round( 0.4 ) << " " << std::lround( 0.4 ) << " " << std::llround( 0.4 ) << std::endl ;
    std::cout << std::round( 0.5 ) << " " << std::lround( 0.5 ) << " " << std::llround( 0.5 ) << std::endl ;
    std::cout << std::round( 0.6 ) << " " << std::lround( 0.6 ) << " " << std::llround( 0.6 ) << std::endl ;
}

另一种选择,也从C99会 std::小数部分保留 其中:

计算接近的整数不大幅度比arg.

#include <iostream>
#include <cmath>

int main()
{
    std::cout << std::trunc( 0.4 ) << std::endl ;
    std::cout << std::trunc( 0.9 ) << std::endl ;
    std::cout << std::trunc( 1.1 ) << std::endl ;

}

如果你需要支持非C++11应用你最好的选择是使用 提高圆,iround,lround,llround提高小数部分保留.

滚你自己版本的圆难

滚你自己可能是不值得的努力, 比看起来难:四舍五入浮到最接近的整数,第1部分, 四舍五入浮到最接近的整数,第2部分四舍五入浮到最接近的整数,部分3 解释一下:

例如一个共同的滚你的实施使用 std::floor 和加入 0.5 不工作的所有投入:

double myround(double d)
{
  return std::floor(d + 0.5);
}

一个输入这将失败是 0.49999999999999994, (看到它的生活).

另一个共同的执行涉及铸造了一个浮点类型的一个组成型,这可以援引不确定的行为的情况下组成部分不能表示在目的地类型。我们可以看到这个草案C++的标准部分 4.9 浮体的转换 它说(重点煤矿):

一prvalue的一个浮点类型的可转换为一个prvalue的 整型。转换截;这是小数部分 被丢弃。 该行为如果不确定的截断值不能 表示在目的地类型。[...]

例如:

float myround(float f)
{
  return static_cast<float>( static_cast<unsigned int>( f ) ) ;
}

给予 std::numeric_limits<unsigned int>::max()4294967295 然后以下呼吁:

myround( 4294967296.5f ) 

会导致溢出,(看到它的生活).

我们可以看到多么困难,这真的是通过查看这个答案 简洁的方式来实现round()C? 其中引用 newlibs 版本的单一精准漂浮的圆。这是一个很长的函数的东西似乎很简单。这似乎是不可能的,任何人都没有熟悉的浮点的实现方式可以正确地实施这一功能:

float roundf(x)
{
  int signbit;
  __uint32_t w;
  /* Most significant word, least significant word. */
  int exponent_less_127;

  GET_FLOAT_WORD(w, x);

  /* Extract sign bit. */
  signbit = w & 0x80000000;

  /* Extract exponent field. */
  exponent_less_127 = (int)((w & 0x7f800000) >> 23) - 127;

  if (exponent_less_127 < 23)
    {
      if (exponent_less_127 < 0)
        {
          w &= 0x80000000;
          if (exponent_less_127 == -1)
            /* Result is +1.0 or -1.0. */
            w |= ((__uint32_t)127 << 23);
        }
      else
        {
          unsigned int exponent_mask = 0x007fffff >> exponent_less_127;
          if ((w & exponent_mask) == 0)
            /* x has an integral value. */
            return x;

          w += 0x00400000 >> exponent_less_127;
          w &= ~exponent_mask;
        }
    }
  else
    {
      if (exponent_less_127 == 128)
        /* x is NaN or infinite. */
        return x + x;
      else
        return x;
    }
  SET_FLOAT_WORD(x, w);
  return x;
}

另一方面如果没有其他的解决方案都是可以使用 newlib 可能是一个选项,因为它是一个经过良好测试的执行情况。

这可能是值得一提的是,如果你想从四舍五入你不需要通过任何小区或地面传递给它的整数结果。即,

int round_int( double r ) {
    return (r > 0.0) ? (r + 0.5) : (r - 0.5); 
}

有(根据 HTTP是可用自C ++ 11在CMATH ://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf

#include <cmath>
#include <iostream>

int main(int argc, char** argv) {
  std::cout << "round(0.5):\t" << round(0.5) << std::endl;
  std::cout << "round(-0.5):\t" << round(-0.5) << std::endl;
  std::cout << "round(1.4):\t" << round(1.4) << std::endl;
  std::cout << "round(-1.4):\t" << round(-1.4) << std::endl;
  std::cout << "round(1.6):\t" << round(1.6) << std::endl;
  std::cout << "round(-1.6):\t" << round(-1.6) << std::endl;
  return 0;
}

输出:

round(0.5):  1
round(-0.5): -1
round(1.4):  1
round(-1.4): -1
round(1.6):  2
round(-1.6): -2

它通常实现为floor(value + 0.5)

编辑:而且它可能不叫一轮,因为至少有三个舍入算法我知道的:向零,轮最接近的整数,而银行家的舍入。您所要求的轮最接近的整数。

有2个问题,我们正在寻找:

  1. 四舍五入换算
  2. 类型的转换。

四舍五入换算平均四舍五入±浮/双到最近的楼层/ceil浮/倍。可能是你的问题在这里结束。但如果你预计要返回Int/漫长的,需要执行的类型转换,并因此"溢出"的问题可能会打你的解决方案。因此,做检查的错误,在你的功能

long round(double x) {
   assert(x >= LONG_MIN-0.5);
   assert(x <= LONG_MAX+0.5);
   if (x >= 0)
      return (long) (x+0.5);
   return (long) (x-0.5);
}

#define round(x) ((x) < LONG_MIN-0.5 || (x) > LONG_MAX+0.5 ?\
      error() : ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))

自: http://www.cs.tut.fi/~jkorpela/round.html

一个特定类型的舍入也在升压实施:

#include <iostream>

#include <boost/numeric/conversion/converter.hpp>

template<typename T, typename S> T round2(const S& x) {
  typedef boost::numeric::conversion_traits<T, S> Traits;
  typedef boost::numeric::def_overflow_handler OverflowHandler;
  typedef boost::numeric::RoundEven<typename Traits::source_type> Rounder;
  typedef boost::numeric::converter<T, S, Traits, OverflowHandler, Rounder> Converter;
  return Converter::convert(x);
}

int main() {
  std::cout << round2<int, double>(0.1) << ' ' << round2<int, double>(-0.1) << ' ' << round2<int, double>(-0.9) << std::endl;
}

请注意,这仅适用,如果你做了到整数的转换。

您可以舍入到n个数字精度:

double round( double x )
{
const double sd = 1000; //for accuracy to 3 decimal places
return int(x*sd + (x<0? -0.5 : 0.5))/sd;
}

如果您最终希望将double功能的round()输出转换为int,那么这个问题的解决方案的接受将是这个样子:

int roundint(double r) {
  return (int)((r > 0.0) ? floor(r + 0.5) : ceil(r - 0.5));
}

我的机器在周围的 8.88纳秒:此时钟时在均匀的随机值通过。

在下面是相同的功能,据我所知,但 2.48纳秒我的机器上时钟的,对于一个显著的性能优势:

int roundint (double r) {
  int tmp = static_cast<int> (r);
  tmp += (r-tmp>=.5) - (r-tmp<=-.5);
  return tmp;
}

其中的原因更好的性能是跳过的支化。

这些日子它不应该是一个问题,使用C++11编译器,包括C99/C++11的数学图书馆。但是,那么问题就变成:其四舍五入的功能做你挑选的?

C99/C++11 round() 往往是没有实际上的四舍五入的功能你想要的.它使用一个时髦的四舍五入的方式这一回合从0作的领带打上一半案件(+-xxx.5000).如果你特别想要,四舍五入的方式,或者你在目标C++实现在哪里 round() 是的速度比 rint(), 然后使用(或者仿效其行为与其他的答案在这个问题,把它的面值和仔细地再现,四舍五入的具体行为。)

round()'s四舍五入的不同于默认IEEE754 轮到最近的模式,甚至作为一个领带打.最近甚至避免了统计偏差的平均幅度的数字,但并偏向于偶数。

有两个数学图书馆舍入功能,使用默认当前的四舍五入的方式: std::nearbyint()std::rint(), ,两者加在C99/C++11,使他们可以任何时间 std::round() 是。唯一的区别是 nearbyint 从来没有提出了FE_INEXACT.

喜欢 rint() 对于业绩原因:海湾合作委员会和铛内联它更加容易,但是海湾合作委员会从来没有内联 nearbyint() (甚至有 -ffast-math)


海湾合作委员会/铛x86-64和AArch64

我把一些 试验的功能上马特Godbolt的编译器Explorer, ,在这里你可以看到源+asm输出(为多个编译器).更多读书的编译器的输出,看到 这Q&A, 和马特的CppCon2017的谈话: "什么有我的编译为我做吗?Unbolting编译器的盖子",

在FP代码,它通常是一个巨大的胜利为联少的职能。特别是在非Windows,其中标准的呼吁《公约》没有电话-保留注册,所以编译器不能让任何FP值在XMM寄存器跨越 call.所以即使你真的不知道asm,你仍然可以很容易地看到它是否只是一个尾巴-打电话给库功能,或是否它内联一个或两个数学的指示。任何内联一个或两个说明是更好的比功能的电话(对于这个特定任务上x86或臂)。

在x86,任何内联至SSE4.1 roundsd 可以自动矢量与SSE4.1 roundpd (或参考 vroundpd).(P->整数转换也可在包装单指令的形式,除了P->64位整数,其中要求AVX512.)

  • std::nearbyint():

    • x86铛:内联到一个单一的insn与 -msse4.1.
    • x86海湾合作委员会:内联到一个单一的insn只有 -msse4.1 -ffast-math, ,只有在海湾合作委员会和5.4 .后海湾合作委员会从来没有内联它(他们也许没有意识到一位可以立即制止不精确例外?那是什么铛使用,但是老年海湾合作委员会使用的同样立即作为 rint 当它内联它)
    • AArch64gcc6.3:内联到一个单一的insn默认。
  • std::rint:

    • x86铛:内联到一个单一的insn与 -msse4.1
    • x86gcc7:内联到一个单一的insn与 -msse4.1.(没有SSE4.1的内联几说明)
    • x86gcc6.x和前:内联到一个单一的insn与 -ffast-math -msse4.1.
    • AArch64海湾合作委员会:内联到一个单一的insn通过默认
  • std::round:

    • x86铛:不行内
    • x86海湾合作委员会:内联的多个指令 -ffast-math -msse4.1, 需要两个矢量的常数。
    • AArch64海湾合作委员会:内联到一个单一的指令(硬件支持这四舍五入的方式,以及如IEEE默认和大多数其他人。)
  • std::floor / std::ceil / std::trunc

    • x86铛:内联到一个单一的insn与 -msse4.1
    • x86gcc7.x:内联到一个单一的insn与 -msse4.1
    • x86gcc6.x和前:内联到一个单一的insn与 -ffast-math -msse4.1
    • AArch64海湾合作委员会:内联默认情况下,一个单个指令

四舍五入到 int / long / long long:

你有两个选择:使用 lrint (喜欢 rint 但是,返回 long, 或 long long 对于 llrint),或者使用一个P->FP四舍五入功能,然后转换为一个整数类型的正常方式(与截).一些编译器化的一种方式比其他的更好。

long l = lrint(x);

int  i = (int)rint(x);

注意, int i = lrint(x) 转换 floatdouble -> long 第一,然后截断整数 int.这有差别的范围整数:不确定的行为在C++、但定义为x86FP->int的说明(编译器将这些的除非它认为UB在编制时间,而这样做不断传播,那么它允许使代码,打破,如果它没有执行)。

在x86、一个P->整数,转换溢出整数产生 INT_MINLLONG_MIN (比特的图案 0x8000000 或64位相当,只是标志位置).英特尔调用这种"整数无限期"的价值。(见 cvttsd2si 手工输入, ,SSE2指令转换(与截)双重标签署整数。它提供了32或64位整数的目的地(在64位的模式)。还有一个 cvtsd2si (转换成当前四舍五入的方式),它是什么,我们编译器发,但不幸的是,海湾合作委员会和铛不会这么做没有 -ffast-math.

还要注意的是FP/从 unsigned int/长效率较低,在x86(不AVX512).转换为32位无符号在64位机是非常便宜;只是转换到64位签署和截断。但是,否则它的显着放缓。

  • x86铛用/不 -ffast-math -msse4.1: (int/long)rint 内联到 roundsd / cvttsd2si.(错过了最优化来 cvtsd2si). lrint 不行内。

  • x86gcc6.x和前没有 -ffast-math:既没有内联的方式

  • x86gcc7没有 -ffast-math: (int/long)rint 回合,并将单独(2总的指示SSE4.1启用,否则一堆码内联为 rint 没有 roundsd). lrint 没有内联。
  • x86海湾合作委员会 -ffast-math: 所有的方式行内到 cvtsd2si (最佳), ,不需要SSE4.1.

  • AArch64gcc6.3没有 -ffast-math: (int/long)rint 内联至2的说明。 lrint 不行内

  • AArch64gcc6.3 -ffast-math: (int/long)rint 汇编到一个电话来 lrint. lrint 没有内联。这可能是一个错过了最优化,除非两个说明我们得到没有 -ffast-math 是非常缓慢。

当心floor(x+0.5)的。下面是可在范围发生什么因为奇数[2 ^ 52,2 ^ 53]:

-bash-3.2$ cat >test-round.c <<END

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

int main() {
    double x=5000000000000001.0;
    double y=round(x);
    double z=floor(x+0.5);
    printf("      x     =%f\n",x);
    printf("round(x)    =%f\n",y);
    printf("floor(x+0.5)=%f\n",z);
    return 0;
}
END

-bash-3.2$ gcc test-round.c
-bash-3.2$ ./a.out
      x     =5000000000000001.000000
round(x)    =5000000000000001.000000
floor(x+0.5)=5000000000000002.000000

这是 http://bugs.squeak.org/view.php?id = 7134 。使用像@konik的一个溶液中。

我自己可靠的版本会是这样的:

double round(double x)
{
    double truncated,roundedFraction;
    double fraction = modf(x, &truncated);
    modf(2.0*fraction, &roundedFraction);
    return truncated + roundedFraction;
}

另一个原因,以避免地板(X + 0.5)在这里一>

没有必要实施任何东西,所以我不知道为什么这么多的答案涉及定义、职能或方法。

在C99

我们有以下和头部 <tgmath.h> 类型一般宏。

#include <math.h>
double round (double x);
float roundf (float x);
long double roundl (long double x);

如果你不能编纂这个,你可能已经离开了数学图书馆。一个类似的命令,这适用于所有C编译器,我们(几个).

gcc -lm -std=c99 ...

C++11

我们有以下和其他重载在包括 <cmath> 依赖IEEE双精度浮点。

#include <math.h>
double round (double x);
float round (float x);
long double round (long double x);
double round (T x);

还有 等同的标准名称空间 太。

如果你不能编纂这个,你可以使用C编译,而不是C++。以下基本命令产生既不是错误警告,也不与克++6.3.1,x86_64-w64-mingw32-g++6.3.0,铛-x86_64++3.8.0,并视C++2015年的社区。

g++ -std=c++11 -Wall

有的序号分

当划分两个序号,其中T短,int长,或另一个序号,四舍五入的表情是这样的。

T roundedQuotient = (2 * integerNumerator + 1)
    / (2 * integerDenominator);

准确度

毫无疑问,奇怪的看不准确出现在浮点运作,但这只是时数字显示,与四舍五入。

来源不仅仅是数量的显着位数的尾数IEEE表示的一个浮点数目,它关系到我们的十进制的思维作为人类。

十产品中的五个,两个,5和2是相对的总理。因此IEEE浮点标准,不可能表示完全数字为所有的二进制数字表示。

这不是一个问题与四舍五入的算法。这是数学的现实,应该认为在选择类型和设计的计算、数据输入和显示的数字。如果应用程序显示的数字显示这些十二进制转换问题,然后应用程序是在视觉上表达准确性,不存在数字现实和应该改变。

功能 double round(double) 与使用 modf 功能:

double round(double x)
{
    using namespace std;

    if ((numeric_limits<double>::max() - 0.5) <= x)
        return numeric_limits<double>::max();

    if ((-1*std::numeric_limits<double>::max() + 0.5) > x)
        return (-1*std::numeric_limits<double>::max());

    double intpart;
    double fractpart = modf(x, &intpart);

    if (fractpart >= 0.5)
        return (intpart + 1);
    else if (fractpart >= -0.5)
        return intpart;
    else
        return (intpart - 1);
    }

将编译整洁,包括"数学。h"和"限制"是必要的。功能工作的根据以下四舍五入的架构:

  • 圆的5.0是5.0
  • 轮3.8是4.0
  • 轮2.3是2.0
  • 圆1.5是2.0
  • 轮0.501为1.0
  • 圆的0.5为1.0
  • 轮0.499为0.0
  • 圆的0.01为0.0
  • 轮0.0is0.0
  • 轮-0.01是-0.0
  • 轮-0.499是-0.0
  • 圆形的-0.5是-0.0
  • 轮-0.501是为-1.0
  • 圆形的-1.5是为-1.0
  • 圆2.3是的-2.0
  • 轮-3.8是-4.0
  • 轮增至5.0为-5.0

如果您需要能够在支持C ++ 11的标准,还需要能够编译环境相同的代码不支持它的环境中编译代码,你可以使用函数宏的std ::轮(),并为每个系统自定义功能之间进行选择。只是通过-DCPP11/DCPP11到11兼容的C ++编译器(或使用其内置的版本宏),并作出这样的标题:

// File: rounding.h
#include <cmath>

#ifdef CPP11
    #define ROUND(x) std::round(x)
#else    /* CPP11 */
    inline double myRound(double x) {
        return (x >= 0.0 ? std::floor(x + 0.5) : std::ceil(x - 0.5));
    }

    #define ROUND(x) myRound(x)
#endif   /* CPP11 */

有关一个简单的例子,请参见 http://ideone.com/zal709

此近似的std ::在不是11兼容的C ++的环境中,包括符号位的保存为-0.0轮()。这可能会导致轻微的性能命中,但是,将可能有与舍入某些已知的“有问题”的问题浮点值如0.49999999999999994或类似的值。

另外,如果你有机会到11兼容的C ++编译器,你可以只抢的std ::轮()从其<cmath>头,并用它来使自己的头,它定义的函数,如果它是不是已经定义。请注意,这可能不是一个最佳的解决方案,但是,特别是如果你需要编译为多个平台。

根据Kalaxy的反应,以下是舍入任何浮点数基于天然舍入最接近的整数类型模板化的解决方案。如果该值超出整数类型的范围内,从而大致作为一个可行的库函数它还抛出在调试模式错误。

    // round a floating point number to the nearest integer
    template <typename Arg>
    int Round(Arg arg)
    {
#ifndef NDEBUG
        // check that the argument can be rounded given the return type:
        if (
            (Arg)std::numeric_limits<int>::max() < arg + (Arg) 0.5) ||
            (Arg)std::numeric_limits<int>::lowest() > arg - (Arg) 0.5)
            )
        {
            throw std::overflow_error("out of bounds");
        }
#endif

        return (arg > (Arg) 0.0) ? (int)(r + (Arg) 0.5) : (int)(r - (Arg) 0.5);
    }

如在评论和其他的答案指出的那样,ISO C ++标准库没有添加round()直到ISO C ++ 11,当该功能是通过参考ISO C99标准数学库拉入。

有关在正操作数[1/2 UB ] round(x) == floor (x + 0.5),其中 UB 是2 23当映射到IEEE-754为float (2008年)binary32,和2 52 double当它被映射到IEEE-754(2008)binary64。数字23和52对应于数存储在这两个浮点格式的尾数位。对于正的操作数[0,1/2)round(x) == 0,和用于在( UB ,+∞正操作数根据round(x) == x。作为功能是关于x轴对称的,负参数x可以处理到round(-x) == -round(x)

这导致下面的紧凑的代码。它编译成跨各种平台的机器指令的合理数量。我观察到GPU上,最紧凑的代码,其中my_roundf()大约需要十几个指令。取决于处理器的体系结构和工具链,这浮点基础的方法可以是任一比从newlib在引用的基于整数的实现更快或更慢不同的答案

我测试my_roundf()详尽反对使用英特尔编译版本13中的newlib roundf()实施方式中,与两个/fp:strict/fp:fast。我还检查了newlib版本的英特尔编译器的roundf()mathimf匹配。详尽的测试是不可能的双精度round(),但是代码是结构上等同于单精度实现。

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <math.h>

float my_roundf (float x)
{
    const float half = 0.5f;
    const float one = 2 * half;
    const float lbound = half;
    const float ubound = 1L << 23;
    float a, f, r, s, t;
    s = (x < 0) ? (-one) : one;
    a = x * s;
    t = (a < lbound) ? x : s;
    f = (a < lbound) ? 0 : floorf (a + half);
    r = (a > ubound) ? x : (t * f);
    return r;
}

double my_round (double x)
{
    const double half = 0.5;
    const double one = 2 * half;
    const double lbound = half;
    const double ubound = 1ULL << 52;
    double a, f, r, s, t;
    s = (x < 0) ? (-one) : one;
    a = x * s;
    t = (a < lbound) ? x : s;
    f = (a < lbound) ? 0 : floor (a + half);
    r = (a > ubound) ? x : (t * f);
    return r;
}

uint32_t float_as_uint (float a)
{
    uint32_t r;
    memcpy (&r, &a, sizeof(r));
    return r;
}

float uint_as_float (uint32_t a)
{
    float r;
    memcpy (&r, &a, sizeof(r));
    return r;
}

float newlib_roundf (float x)
{
    uint32_t w;
    int exponent_less_127;

    w = float_as_uint(x);
    /* Extract exponent field. */
    exponent_less_127 = (int)((w & 0x7f800000) >> 23) - 127;
    if (exponent_less_127 < 23) {
        if (exponent_less_127 < 0) {
            /* Extract sign bit. */
            w &= 0x80000000;
            if (exponent_less_127 == -1) {
                /* Result is +1.0 or -1.0. */
                w |= ((uint32_t)127 << 23);
            }
        } else {
            uint32_t exponent_mask = 0x007fffff >> exponent_less_127;
            if ((w & exponent_mask) == 0) {
                /* x has an integral value. */
                return x;
            }
            w += 0x00400000 >> exponent_less_127;
            w &= ~exponent_mask;
        }
    } else {
        if (exponent_less_127 == 128) {
            /* x is NaN or infinite so raise FE_INVALID by adding */
            return x + x;
        } else {
            return x;
        }
    }
    x = uint_as_float (w);
    return x;
}

int main (void)
{
    uint32_t argi, resi, refi;
    float arg, res, ref;

    argi = 0;
    do {
        arg = uint_as_float (argi);
        ref = newlib_roundf (arg);
        res = my_roundf (arg);
        resi = float_as_uint (res);
        refi = float_as_uint (ref);
        if (resi != refi) { // check for identical bit pattern
            printf ("!!!! arg=%08x  res=%08x  ref=%08x\n", argi, resi, refi);
            return EXIT_FAILURE;
        }
        argi++;
    } while (argi);
    return EXIT_SUCCESS;
}

我使用下面的实施一轮中ASM为x86架构和MS VS特定C ++:

__forceinline int Round(const double v)
{
    int r;
    __asm
    {
        FLD     v
        FISTP   r
        FWAIT
    };
    return r;
}

UPD:返回双精度值

__forceinline double dround(const double v)
{
    double r;
    __asm
    {
        FLD     v
        FRNDINT
        FSTP    r
        FWAIT
    };
    return r;
}

输出:

dround(0.1): 0.000000000000000
dround(-0.1): -0.000000000000000
dround(0.9): 1.000000000000000
dround(-0.9): -1.000000000000000
dround(1.1): 1.000000000000000
dround(-1.1): -1.000000000000000
dround(0.49999999999999994): 0.000000000000000
dround(-0.49999999999999994): -0.000000000000000
dround(0.5): 0.000000000000000
dround(-0.5): -0.000000000000000

要四舍五入由“n”位小数的浮动值的最佳方式,是与为O以下的(1)的时间: -

我们有由3个地方四舍五入的值即n = 3.So,

float a=47.8732355;
printf("%.3f",a);
// Convert the float to a string
// We might use stringstream, but it looks like it truncates the float to only
//5 decimal points (maybe that's what you want anyway =P)

float MyFloat = 5.11133333311111333;
float NewConvertedFloat = 0.0;
string FirstString = " ";
string SecondString = " ";
stringstream ss (stringstream::in | stringstream::out);
ss << MyFloat;
FirstString = ss.str();

// Take out how ever many decimal places you want
// (this is a string it includes the point)
SecondString = FirstString.substr(0,5);
//whatever precision decimal place you want

// Convert it back to a float
stringstream(SecondString) >> NewConvertedFloat;
cout << NewConvertedFloat;
system("pause");

这可能是转换的低效肮脏的方式,但心里很不舒服,它的工作原理笑。而且它的好,因为它适用于实际的浮动。不仅影响输出视觉上。

我这样做:

#include <cmath.h>

using namespace std;

double roundh(double number, int place){

    /* place = decimal point. Putting in 0 will make it round to whole
                              number. putting in 1 will round to the
                              tenths digit.
    */

    number *= 10^place;
    int istack = (int)floor(number);
    int out = number-istack;
    if (out < 0.5){
        floor(number);
        number /= 10^place;
        return number;
    }
    if (out > 0.4) {
        ceil(number);
        number /= 10^place;
        return number;
    }
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top