【问题标题】:How to extract fractional part of a double value without rounding in c如何在不四舍五入的情况下提取双精度值的小数部分
【发布时间】:2021-08-01 09:37:03
【问题描述】:

当我尝试提取双精度的小数部分时,它似乎在 C 中四舍五入,有没有办法在不四舍五入的情况下做到这一点?

    double t = 8.2;
    int ipart = (int)t;
    long long val = abs((long long)(t*1000000));
    long long fpart = (val)%1000000;

fpart 给出 199999,有没有办法在不四舍五入的情况下将其设为 200000?尝试了很多方法,但似乎没有一种方法适用于所有数字。

目的是最终将此双精度转换为字符串,其确切值应为“8.20000”。如果我可以提取 long long 变量中的小数部分,那么我可以使用 snprintf 生成字符串。

【问题讨论】:

    标签: c floating-point type-conversion double fractions


    【解决方案1】:

    值 8.2 不能以二进制浮点数精确表示。实际值更接近 8.19999999999999929。

    因此,你不得不四舍五入:

    long long val = llabs(round(t*1000000));
    

    或者在转换前将值加0.5:

    long long val = llabs((t*1000000) + 0.5);
    

    【讨论】:

    • 0.5 方法存在一些问题,例如对负数和非常大的数给出错误的结果。 round 旨在应对所有情况
    【解决方案2】:

    如何在不四舍五入的情况下提取双精度值的小数部分...?

    使用标准 C 库中的 modf()

    #include <math.h>
    
    double ipart;
    double fraction = modf(value, &ipart);
    printf("Fraction %g\n", fraction);
    printf("Whole number %g\n", ipart);
    

    modf 函数将参数值分解为整数和小数部分,每个部分都与参数具有相同的类型和符号。它们将整数部分(以浮点格式)存储在 iptr 指向的对象中。
    C17dr § 7.12.6.12 2


    深入了解 8.2

    double 可以代表大约 264 个不同的值正好。 8.2 不是其中之一。

    对于double t = 8.2;t 采用附近的值,即 8.199999999999999289457264239899814128875732421875 或
    81801439850948192/9007199254740992 由于常见 double 的二进制性质。
    要查找分数,请使用fraction*pow(2,DBL_MANT_DIG)/pow(2,DBL_MANT_DIG)

    因此,对于t 的小数部分,“将其作为 200000不四舍五入”作为 200000/分母的目标是不可能的。

    【讨论】:

    • 我想你可能想要double fraction = modf(value, &amp;ipart);
    • @chux:感谢您的明确解释,但我的意图是将这个 double 转换为字符串,我无法使用 snprintf 获得确切的值,这就是为什么想到提取 long 中的分数然后转换串起来。但是这种方式看起来我必须再次将它加倍,这将再次给出相同的舍入值。
    • @chux:当我执行“long long val = abs((long long)(t*10000));”时,val 变为 82000 但“long long val = abs((long long) (t*1000000)); " val 变为 8199999,知道为什么会有差异吗?
    • @Scarlet 8.199999999999999289457264239899814128875732421875 * 10000 最接近82000.0 或略高于。 8.199999999999999289457264239899814128875732421875 * 1000000 最接近于 8200000.0 之下的轮次。在第二种情况下转换为 long long 会导致 0.999...(注意:abs() 是应用于 long longint 函数。研究 llabs(), lround()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-07
    • 1970-01-01
    • 1970-01-01
    • 2015-01-06
    • 2014-10-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多