舍入浮点数的源代码

Posted

技术标签:

【中文标题】舍入浮点数的源代码【英文标题】:Source code to round floating point number 【发布时间】:2014-04-03 11:28:08 【问题描述】:

除了使用ceilfloor 之类的任何内置函数之外,如何舍入浮点数?

我想将 2.10 转换为 2.14-> 2.1 和 2.15 转换为 2.19 -> 2.2

我写了一些逻辑,但卡在中间

    float a = 2.24;
    int b = a*100;
    int result n, i =0;
    while(i>2)
    
        n = b%10;
        i++;
    
    if(n >5)
    
      c = b%10;
      c = c/10 + 1;
    

我尝试了很多内置函数,但所有这些都不适用于我的 diab 编译器

//  totalDist = roundf(totalDist * 10) / 10.0;      
//  totalDist = floor(totalDist * pow(10., 1) + .5) / pow(10., 1);  
    totalDist = floorf(totalDist * 10 + 0.5) / 10;

打算自己写逻辑

【问题讨论】:

为什么“除了使用任何内置函数”? totalDist = floorf(totalDist * 10 + 0.5) / 10; 似乎是正确的,但您可以使用浮点类型文字:10.0f0.5f 【参考方案1】:
float a = 2.24;
float b = roundf(a*10.0f)/10.0f;//roundf in C99

【讨论】:

+1 对于 1) 适用于正数和负数的解决方案,2) 不限于 int 范围和 3) 是精确的。 (建议使用 10.0f 而不是 10.0)。 @chux 我按照你的提议改了。 @Kerrek SB 我曾经也这么认为。我对 C 规范的评论没有找到支持。它似乎取决于FLT_EVAL_METHOD。如果为 0,则“仅根据类型的范围和精度评估所有操作和常量;”如果为 1,则“将 float 和 double 类型的操作和常量评估为 double 类型的范围和精度......”。存在其他设置。 @chux:你是对的,没关系 - 算术转换允许两个操作数都是浮点数。【参考方案2】:

试试int((x + 0.05) * 10.0) / 10.0

您也可以使用trunc,而不是与int 之间的转换。

或者你可以使用roundround(x * 10.0) / 10.0

【讨论】:

int() 将在整数范围外失败。 trunc() 将在负数上失败。您可以改用floor() @Vovanium:在整数范围之外,浮点数也没有子单位精度。 OP 没有指定负数的行为,但这确实有待决定。 首先,标准将最小整数范围定义为 -32767..32767,它小于大多数可用的浮点精度。其次,即使对于大数(例如 1E10),舍入也是不可能的,函数可以返回正确的值,而不是溢出。【参考方案3】:

因为我的旧答案需要大量仔细编程才能使其发挥作用

我提出了另一种实现轮函数的方法:

您可以轻松检查(正/负)数字是否会四舍五入 或下降(加/减)0.5。然后你可以截断结果 并接受你的答案。此外,为了支持更深层次的轮作为 你想要你可以让用户指定多少位小数 想要,瞧:

long double round_f(long double number, int decimal_places)

     assert(decimal_places > 0);

     double power = pow(10, decimal_places-1);
     number *= power;

     return (number >= 0) ? ((long long)(number + 0.5))/power : ((long long)(number - 0.5))/power;

And here you can see a working example.

旧的:

你可以使用冲刺:

#include <stdio.h>

int main(void)

    float a = 2.24;
    int size;
    char num[8] = 0;
    sprintf(num, "%d", (int) (a * 100));

    for (size=0; num[size]; size++);

    size--;

    if (num[size] < '5') 
        num[size] = '0';
     else 
        num[size] = '0';
        if (num[size-1] == '9')
            num[size-1] = '0';
        else
            num[size-1]++;
    

    printf("a = %f\n", a);
    printf("num = %s\n", num);

    return(0);

你可以看到逻辑。最后,您可以将字符串恢复为整数并乘以 100。

编辑:这只是逻辑。请参阅下面的 cmets,了解完全工作所需的条件。

【讨论】:

最终数字为 220,实际结果预期为 2.3 此方法对a &gt; 100000.0 失败。对于像3.99 这样的数字,它会失败。它失败了a &lt; -10000.0a*100 超大 int 范围失败。 是的。我知道。我只想展示它背后的逻辑。您可以轻松地用循环替换检查 9 的嵌套 if。您还可以使字符数组更大,数字更大。您也可以将第一个位置留空以避免“溢出”(对于像 99.99 这样的情况下的进位)。 同意这是一个方法背后的逻辑的一般演示,而不是一个完整的解决方案:(float --> int --> sprintf --> char processing --> 隐蔽回浮动) .断言它“可以轻松替换”,但不发布掩盖了微妙问题:有限的int 范围、字符缓冲区溢出、算术溢出处理。 @chux 我更改了答案以满足您的标准,我相信。你怎么看?感谢 cmets。【参考方案4】:

如果您只是想将数字四舍五入以用于输出目的,那么%.1f 格式字符串确实是正确答案。

printf("%.1f", 2.14);

或 如果你真的想四舍五入,那么像这样的工作

#include <math.h>

float val = 37.777779;

float rounded_down = floorf(val * 100) / 100;   /* Result: 37.77 */
float nearest = floorf(val * 100 + 0.5) / 100;  /* Result: 37.78 */
float rounded_up = ceilf(val * 100) / 100;      /* Result: 37.78 */

通常我们使用nearest方法

【讨论】:

注意:floorf(val * 100 + 0.5) 对负数失败。【参考方案5】:

BLUEPIXY 的回答很好。但总的来说;浮点乘法比除法快,所以如果速度是相关的;乘以 0.1 而不是除以 10。

【讨论】:

我尝试了所有这些 // totalDist = roundf(totalDist * 10) / 10.0; // totalDist = floor(totalDist * pow(10., 1) + .5) / pow(10., 1); totalDist = floorf(totalDist * 10 + 0.5) / 10;

以上是关于舍入浮点数的源代码的主要内容,如果未能解决你的问题,请参考以下文章

使用 0.5 规则舍入浮点数的方法

用 f 字符串舍入浮点数 [重复]

舍入浮点数的最短函数c ++

舍入浮点数,然后转到语言环境字符串

为什么舍入浮点数1.4999999999999999产生2?

C中的printf如何对浮点数进行舍入?