我正在编写一个模板类,旨在使用任何浮点类型。对于某些方法,我需要将数字拆分为其整数和小数部分。对于原始浮点类型,我可以强制转换为整数来截断小数部分,但这不适用于大数字类。理想情况下,我的班级只会在计算中使用四种基本算术运算(加法,减法,乘法,除法)。
以下方法是我提出的解决方案。所有这一切都是减去10的幂,直到原始数小于1.它运作良好,但似乎是一种蛮力的方法。有没有更有效的方法来做到这一点?
template< typename T >
class Math
{
public:
static T modf( T const & x, T & intpart )
{
T sub = 1;
T ret = x;
while( x >= sub )
{
sub *= 10;
}
sub /= 10;
while( sub >= 1 )
{
while( ret >= sub )
{
ret -= sub;
}
sub /= 10;
}//while [sub] > 0
intpart = x - ret;
return ret;
}
}
请注意,为简洁起见,我删除了签名管理代码。
答案 0 :(得分:2)
您可以用二分搜索替换减法循环,尽管这不是复杂性类的改进。
你所需要的数量大约等于x
的十进制数之和,而二进制搜索需要大量等于3的加法和除以2的运算。和 - 一位乘以x
的小数位数。
通过你正在做的事情以及二进制搜索,在寻找上限时没有特别的理由使用10的幂,你可以使用任何数字。其他一些数字平均可能会快一些,但可能取决于类型T
。
顺便说一句,我也很想在modf
(或命名空间中的免费模板函数)中使Math
成为函数模板,而不是Math
类模板。这样,您可以为特定类型(尤其是内置类型)一次特化或重载一个函数,而无需专门化整个Math
。
示例:
namespace Math
{
template <typename T>
T modf( T const & x, T & intpart )
{ ... }
}
这样称呼:
float f = 1.5, fint;
std::cout << Math::modf(f, fint) << '\n';
double d = 2.5, dint;
std::cout << Math::modf(d, dint) << '\n';
mpf_class ff(3.5), ffint(0); // GNU multi-precision
std::cout << Math::modf(ff, ffint) << '\n';
像这样重载:
namespace Math {
double modf(double x, double &intpart) {
return std::modf(x, &intpart);
}
mpf_class modf(const mpf_class &x, mpf_class &intpart) {
intpart = floor(x);
return x - intpart;
}
}
答案 1 :(得分:0)
#include <cmath>
#include <iostream>
template<typename T>
class Math
{
public:
static T modf(const T& x, T& integral_part)
{
return std::modf(x, &integral_part);
}
};
int main()
{
double d_part = 0.;
double res = Math<double>::modf(5.2123, d_part);
std::cout << d_part << " " << res << std::endl;
}
答案 2 :(得分:0)
我不知道你的“理想上只使用数学运算”的限制是多么严格,但是对于小数部分,你能将它提取到字符串并转换回浮点数吗?