2

我正在编写一个模板类,旨在与任何浮点类型一起使用。对于某些方法,我需要将一个数字分成整数部分和小数部分。使用原始浮点类型,我可以只转换为整数来截断小数部分,但这不适用于大数字类。理想情况下,我的班级在计算中只使用四种基本算术运算(加法、减法、乘法、除法)。

下面的方法是我想出的解决方案。它所做的只是减去 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;
    }
}

请注意,为简洁起见,我删除了标志管理代码。

4

3 回答 3

2

您也许可以用二进制搜索替换减法循环,尽管这不是复杂性类的改进。

您所拥有的需要的减法次数大约等于 的十进制数字的总和x,而二进制搜索需要多次加法和除以二的运算,大约等于数字的 3 位乘以的十进制数字x

使用你正在做的事情和二分搜索,在寻找上限时没有特别的理由使用 10 的幂,你可以使用任何数字。平均而言,其他一些数字可能会更快一些,尽管它可能取决于 type 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;
    }
}
于 2012-07-04T09:24:08.953 回答
0

mb 使用 std::modf 更好吗?对于自定义类型,您可以发布 Math 类专业化。

#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;
}
于 2012-07-04T09:19:19.733 回答
0

我不知道您的“理想情况下仅使用数学运算”限制有多严格,但是对于小数部分,您可以将其提取为字符串并转换回浮点数吗?

于 2012-07-04T09:23:54.053 回答