65.9K
CodeProject 正在变化。 阅读更多。
Home

一些有用的双精度小数函数

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.22/5 (10投票s)

2008年2月20日

CPOL

1分钟阅读

viewsIcon

37543

四舍五入、小数位数等。

引言

我经常使用 math.h 中的函数。但是,缺少一些函数,所以我自己编写了一些。它们是处理小数位的简单函数。没有什么特别的。但有时它们会很有用。

使用代码

这些函数简单明了,不言自明。这些函数依赖于 math.h(仅依赖 math.h)。

#include "math.h"

Round() 将双精度浮点数四舍五入到指定的位数。它与 Excel 的 Round 函数非常相似。

// rounds a double variable to nPlaces decimal places
double Round(double dbVal, int nPlaces /* = 0 */)
{
    const double dbShift = pow(10.0, nPlaces);
    return  floor(dbVal * dbShift + 0.5) / dbShift; 
}

GetDecimalPlaces() 计算并返回 double 的小数位数(请参阅注释 1)。

// get the number of decimal places
int GetDecimalPlaces(double dbVal)
{
    static const int MAX_DP = 10;
    static const double THRES = pow(0.1, MAX_DP);
    if (dbVal == 0.0)
        return 0;
    int nDecimal = 0;
    while (dbVal - floor(dbVal) > THRES && nDecimal < MAX_DP)
    {
        dbVal *= 10.0;
        nDecimal++;
    }
    return nDecimal;
}

GetFmtStr() 创建一个 printf() 样式的格式字符串。

// get the number format string
const char* GetFmtStr(char* szFmt, int nDecimal)
{
    sprintf(szFmt, "%%.%dlf", nDecimal);
    return szFmt;
}

最后,RoundUD() 将双精度浮点数四舍五入或向下舍入到 dbUnit 步长的最接近值。

// round up/down to certain units
double RoundUD(bool bRoundUp, double dbUnit, double dbVal)
{
    static const int ROUND_DP = 10;
    double dbValInUnit = dbVal / dbUnit;
    dbValInUnit = Round(dbValInUnit, ROUND_DP);
    if (bRoundUp) // round up
        dbValInUnit = ceil(dbValInUnit);
    else // round down
        dbValInUnit = floor(dbValInUnit);
    return (dbValInUnit * dbUnit);
}

您可以使用以下代码测试上述函数

printf("rounding %lf d.p.=%d is %lf\n", 10.0,        1,    Round(10.0,         1));
printf("rounding %lf d.p.=%d is %lf\n", 0.0,         0,    Round(0.0,          1));
printf("rounding %lf d.p.=%d is %lf\n", 0.1,         1,    Round(0.1,          1));
printf("rounding %lf d.p.=%d is %lf\n", 0.01,        1,    Round(0.01,         1));
printf("rounding %lf d.p.=%d is %lf\n", 0.0123456,   0,    Round(0.0123456,    0));
printf("rounding %lf d.p.=%d is %lf\n", 0.0123456,   1,    Round(0.0123456,    1));
printf("rounding %lf d.p.=%d is %lf\n", 0.0123456,   2,    Round(0.0123456,    2));
printf("rounding %lf d.p.=%d is %lf\n", 0.0123456,   6,    Round(0.0123456,    6));
printf("rounding %lf d.p.=%d is %lf\n", -0.0123456,  6,    Round(-0.0123456,   6));
printf("rounding %lf up unit=%lf is %lf\n",   0.0,   0.05, RoundUD(true, 0.05, 0.0));
printf("rounding %lf down unit=%lf is %lf\n", 0.0,   0.05, RoundUD(false, 0.05, 0.0));
printf("rounding %lf up unit=%lf is %lf\n",   0.01,  0.05, RoundUD(true, 0.05, 0.01));
printf("rounding %lf down unit=%lf is %lf\n", 0.01,  0.05, RoundUD(false, 0.05, 0.01));
printf("rounding %lf up unit=%lf is %lf\n",   -0.01, 0.05, RoundUD(true, 0.05, -0.01));
printf("rounding %lf down unit=%lf is %lf\n", -0.01, 0.05, RoundUD(false, 0.05, -0.01));
printf("%lf has %d d.p.\n", 0.0,     GetDecimalPlaces(0.0));
printf("%lf has %d d.p.\n", 10.0,    GetDecimalPlaces(10.0));
printf("%lf has %d d.p.\n", -10.0,   GetDecimalPlaces(-10.0));
printf("%lf has %d d.p.\n", 10.123,  GetDecimalPlaces(10.123));
printf("%lf has %d d.p.\n", -10.123, GetDecimalPlaces(-10.123));
printf("%lf has %d d.p.\n", 10.01,   GetDecimalPlaces(10.01));
printf("%lf has %d d.p.\n", -10.01,  GetDecimalPlaces(-10.01));
char szFmt[32];
printf(GetFmtStr(szFmt, GetDecimalPlaces(0.0)), 0.0); printf("\n");
printf(GetFmtStr(szFmt, GetDecimalPlaces(10.0)), 10.0); printf("\n");
printf(GetFmtStr(szFmt, GetDecimalPlaces(10.010)), 10.010); printf("\n");
printf(GetFmtStr(szFmt, GetDecimalPlaces(-0.0345)), -0.0345); printf("\n");

输出将是这样的

rounding 10.000000 d.p.=1 is 10.000000
rounding 0.000000 d.p.=0 is 0.000000
rounding 0.100000 d.p.=1 is 0.100000
rounding 0.010000 d.p.=1 is 0.000000
rounding 0.012346 d.p.=0 is 0.000000
rounding 0.012346 d.p.=1 is 0.000000
rounding 0.012346 d.p.=2 is 0.010000
rounding 0.012346 d.p.=6 is 0.012346
rounding -0.012346 d.p.=6 is -0.012346
rounding 0.000000 up unit=0.050000 is 0.000000
rounding 0.000000 down unit=0.050000 is 0.000000
rounding 0.010000 up unit=0.050000 is 0.050000
rounding 0.010000 down unit=0.050000 is 0.000000
rounding -0.010000 up unit=0.050000 is 0.000000
rounding -0.010000 down unit=0.050000 is -0.050000
0.000000 has 0 d.p.
10.000000 has 0 d.p.
-10.000000 has 0 d.p.
10.123000 has 3 d.p.
-10.123000 has 3 d.p.
10.010000 has 2 d.p.
-10.010000 has 2 d.p.
0
10
10.01
-0.0345

关注点

  • 注释 1:GetDecimalPlaces() 有一些需要解释的地方。在一个循环中,double 乘以 10,然后与它的向下取整值(截断值)进行比较。如果它们相同,则意味着我们已经耗尽了小数位。由于 double 的内部表示不精确,因此 double 之间的比较很棘手。因此,比较必须允许一定的误差范围。误差范围由 THRES 指定,其设置为 1-10

历史

  • 首次版本:2008 年 2 月 20 日。
© . All rights reserved.