[英]Is there a trunc function in C++?
I searched around and couldn't find the trunc
function for C++.我四处搜索,找不到 C++ 的
trunc
function。 I know I can do this:我知道我可以这样做:
int main()
{
double a = 12.566789;
cout << setprecision(2) << fixed << (int)(a * 100) / 100.0 << endl;
return 0;
}
but I'm not sure it's the best way to do this.但我不确定这是最好的方法。 Thank you.
谢谢你。
If your C library is so old that it lacks a trunc
function (specified in C99), you can easily implement one based on floor
and ceil
(specified in C89)如果您的 C 库太旧以至于缺少
trunc
function(在 C99 中指定),您可以轻松地实现基于floor
和ceil
(在 C89 中指定)的库
double trunc(double d){ return (d>0) ? floor(d) : ceil(d) ; }
trunc
is there, in <cmath>
: trunc
在那里,在<cmath>
:
#include <iostream>
#include <cmath>
int main() {
std::cout << trunc(3.141516) << std::endl;
}
I suppose you're looking for something else?我想你在寻找别的东西?
There's a trunc function in C that you can use in C++ C 中有一个截断 function 可以在 C++ 中使用
trunc(a*100)/100
Keep in mind that you still have to specify formatting requests, because floating point can't represent all real numbers exactly, and you could get output like 12.5600000001
or 12.55999999
if you don't tell the output code the precision you want.请记住,您仍然必须指定格式化请求,因为浮点数不能准确地表示所有实数,如果您不告诉 Z78E6221F6393D1356681DB398F14CE6D 代码您想要的精度,您可以获得像
12.5600000001
或12.55999999
这样的 output。
TL;DR TL;博士
Use the following for output:对 output 使用以下内容:
cout << setprecision(2) << fixed << a<< endl;
And the following if you need a truncated result somewhere during a mathematical calculation:如果在数学计算过程中某处需要截断结果,请执行以下操作:
trunc(a*100)/100
(Or better yet, use fixed-point math.) (或者更好的是,使用定点数学。)
Sure.当然。 Use the
trunc()
function from math.h.使用 math.h 中的
trunc()
function。 It's a C function, but it works as well in C++ as it does in C.这是一个 C function,但它在 C++ 中的效果与在 Z0D61F8370CAD14DE421 中一样好。 If you want to keep a couple digits, you can always:
如果您想保留几个数字,您可以随时:
double a = 12.566789;
double b = trunc(a * 100) / 100.0;
If you're using an ancient C or C++ library that doesn't implement trunc
, use boost::math::trunc
.如果您使用的是未实现
trunc
的古老 C 或 C++ 库,请使用boost::math::trunc
。
I've developed a very fast trunc-function:我开发了一个非常快速的截断函数:
double ftrunc( double d )
{
static_assert(sizeof(double) == sizeof(uint64_t), "sizeof(double) not equal to sizeof(uint64_t)");
static_assert(numeric_limits<double>::is_iec559, "double must be IEEE-754");
// assume size_t is our CPU's native register-width
static_assert(sizeof(size_t) == sizeof(uint64_t) || sizeof(size_t) == sizeof(uint32_t), "register-width must be 32 or 64 bit");
if constexpr( sizeof(size_t) == sizeof(uint64_t) )
// we have 64 bit registers
{
unsigned const MANTISSA_BITS = 52,
EXP_BIAS = 0x3FF,
INF_NAN_BASE = 0x7FF;
uint64_t const EXP_MASK = (uint64_t)0x7FF << MANTISSA_BITS,
SIGN_MASK = (uint64_t)0x800 << MANTISSA_BITS ,
MIN_INTEGRAL_DIGITS_EXP = (uint64_t) EXP_BIAS << MANTISSA_BITS,
MIN_INTEGRAL_ONLY_EXP = (uint64_t)(EXP_BIAS + MANTISSA_BITS) << MANTISSA_BITS,
INF_NAN_EXP = (uint64_t)INF_NAN_BASE << MANTISSA_BITS,
NEG_MANTISSA_MASK = 0x000FFFFFFFFFFFFFu;
union
{
double du;
uint64_t dx;
};
du = d;
uint64_t exp = dx & EXP_MASK;
if( exp >= MIN_INTEGRAL_DIGITS_EXP )
// value has integral digits
if( exp < MIN_INTEGRAL_ONLY_EXP )
{
// there are fraction-digits to mask out, mask them
unsigned shift = (unsigned)(exp >> MANTISSA_BITS) - EXP_BIAS;
dx &= ~(NEG_MANTISSA_MASK >> shift);
return du;
}
else
if( exp < INF_NAN_EXP )
// value is integral
return du;
else
// infinite, NaN, SNaN
// raise exception on SNaN if necessary
return du + du;
else
{
// below +/-1.0
// return +/-0.0
dx &= SIGN_MASK;
return du;
}
}
else if constexpr( sizeof(size_t) == sizeof(uint32_t) )
// we have 32 bit registers
{
unsigned const MANTISSA_BITS = 52,
HI_MANTISSA_BITS = 20,
EXP_BIAS = 0x3FF,
INF_NAN_BASE = 0x7FF;
uint32_t const EXP_MASK = (uint32_t)0x7FFu << HI_MANTISSA_BITS,
SIGN_MASK = (uint32_t)0x800u << HI_MANTISSA_BITS,
MIN_INTEGRAL_DIGITS_EXP = (uint32_t) EXP_BIAS << HI_MANTISSA_BITS,
MAX_INTEGRAL32_EXP = (uint32_t)(EXP_BIAS + HI_MANTISSA_BITS) << HI_MANTISSA_BITS,
MIN_INTEGRAL_ONLY_EXP = (uint32_t)(EXP_BIAS + MANTISSA_BITS) << HI_MANTISSA_BITS,
INF_NAN_EXP = (uint32_t)INF_NAN_BASE << HI_MANTISSA_BITS,
NEG_HI_MANTISSA_MASK = 0x000FFFFFu,
NEG_LO_MANTISSA_MASK = 0xFFFFFFFFu;
union
{
double du;
struct
{
uint32_t dxLo;
uint32_t dxHi;
};
};
du = d;
uint32_t exp = dxHi & EXP_MASK;
if( exp >= MIN_INTEGRAL_DIGITS_EXP )
// value has integral digits
if( exp < MIN_INTEGRAL_ONLY_EXP )
// there are fraction-digits to mask out
if( exp <= MAX_INTEGRAL32_EXP )
{
// the fraction digits are in the upper dword, mask them and zero the lower dword
unsigned shift = (unsigned)(exp >> HI_MANTISSA_BITS) - EXP_BIAS;
dxHi &= ~(NEG_HI_MANTISSA_MASK >> shift);
dxLo = 0;
return du;
}
else
{
// the fraction digits are in the lower dword, mask them
unsigned shift = (unsigned)(exp >> HI_MANTISSA_BITS) - EXP_BIAS - HI_MANTISSA_BITS;
dxLo &= ~(NEG_LO_MANTISSA_MASK >> shift);
return du;
}
else
if( exp < INF_NAN_EXP )
// value is integral
return du;
else
// infinite, NaN, SNaN
// raise exception on SNaN if necessary
return du + du;
else
{
// below +/-1.0
// return +/-0.0
dxHi &= SIGN_MASK;
dxLo = 0;
return du;
}
}
}
It's faster than most implemementations.它比大多数实现都快。 On my Ryzen 7 1800X the average execution-time of values >= 2^0 and <= 2^54 is 12 clock cycles.
在我的 Ryzen 7 1800X 上,值 >= 2^0 和 <= 2^54 的平均执行时间是 12 个时钟周期。
use ceil
or floor
from cmath使用 cmath 的
ceil
或floor
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.