如何在C中进行舍入?

如何在C中进行舍入?,c,floating-point,rounding,C,Floating Point,Rounding,我有一个代码示例: float f = 3.55f; printf("%.1f\n", f); 结果是3.5,而不是期望的3.6 float delta = 1e-7; float f = 3.55f; printf("%.1f\n", f+delta); 现在的结果是3.6,但当f为0.04999f时 printf("%.1f\n", f+delta); 结果是0.1,而不是0.0 我需要一个能将3.55转换为3.6、0.049999转换为0.0的函数,有人给我提供线索吗?与许多浮点问题

我有一个代码示例:

float f = 3.55f;
printf("%.1f\n", f);
结果是3.5,而不是期望的3.6

float delta = 1e-7;
float f = 3.55f;
printf("%.1f\n", f+delta);
现在的结果是3.6,但当f为0.04999f时

printf("%.1f\n", f+delta);
结果是0.1,而不是0.0


我需要一个能将3.55转换为3.6、0.049999转换为0.0的函数,有人给我提供线索吗?

与许多浮点问题一样,问题是您的值:

另见


因此,除非您使用
ceil()
,否则此值永远不会向上取整。

此代码在这里起作用。我对代码进行了注释,以便您能够理解它

    #include <stdio.h>
    #include <stdlib.h>

int main(int argc, char const *argv[])
{
    float delta = 1e-7;
    float f = 3.55f;

    // Here we minus f (3.55) from the integer of f (3) so 3.55 - 3 = 0.55
    // Then we check whether the value is bigger than 0.5
    if( (f-(int)f) >= 0.5 ) { 
            // If it is, then plus 0.01 to the answer. Thus making it 3.65
        f = f + 0.01;
    } else {
            // If its not, minus 0.01 from the answer.
            // Assuming f is 3.44 this will make f 3.43
        f = f - 0.01;
    }

    // Since you its to the first decimal place, the code above will output 
    // your desired result which is 3.6.
    printf("%.1f\n", f+delta);
    return 0;
}
#包括
#包括
int main(int argc,char const*argv[]
{
浮动增量=1e-7;
浮球f=3.55f;
//这里我们从f(3)的整数中减去f(3.55),所以3.55-3=0.55
//然后我们检查该值是否大于0.5
如果((f-(int)f)>=0.5){
//如果是的话,那么答案加上0.01,因此是3.65
f=f+0.01;
}否则{
//如果不是,从答案中减去0.01。
//假设f为3.44,则f为3.43
f=f-0.01;
}
//由于将其保留到第一个小数位,因此将输出上面的代码
//你想要的结果是3.6。
printf(“%.1f\n”,f+delta);
返回0;
}
对的修改产生所需的输出:

float custom_round(float num, int prec)
{
    float trunc = round(num * pow(10, prec+7));
    trunc = round(trunc/pow(10, 7));
    return trunc / pow(10, prec);
}

7
额外精度来自
delta
值。我不认为它是普遍适用的,但对于两个数字
3.55f
0.04999f
,它指出了一个位置,第一个数字将向上取整,而第二个数字将向下取整。

我希望这对您有所帮助。这里有一个完整的取整程序,但您只能使用该函数

#include <stdio.h>
#include <math.h>
#include <string.h>

//function prototypes
float roundon(float n,int to);

void main(){
    //vars
    float num;
    int roundto;
    puts("Enter the decimal to be rounded");
    scanf("%f",&num);

    puts("Enter the number of decimal places to be rounded");
    scanf("%d",&roundto);

    float rounded= roundon(num,roundto);
    printf("The rounded value is %f\n",rounded);
}

//functions
float roundon(float n, int to){
    //vars
    float rounded;

    int checker=(int) (n*pow(10,(to+1)))%10;
    int dec= (int) (n*pow(10,to));
    if(checker>=5){
        dec++;
    }

    rounded= (float) dec/(pow(10,to));
    return (rounded);
}
#包括
#包括
#包括
//功能原型
浮动环行交叉口(浮动n,整数至);
void main(){
//瓦尔斯
浮点数;
国际圆桌会议;

puts(“输入要四舍五入的小数点”); scanf(“%f”、&num); puts(“输入要四舍五入的小数位数”); scanf(“%d”、&roundto); 浮点四舍五入=圆形(num,roundto); printf(“四舍五入值为%f\n”,四舍五入); } //功能 浮动环行交叉口(浮动n,整数到){ //瓦尔斯 浮圆; 整数校验器=(整数)(n*pow(10,(to+1)))%10; 整数dec=(整数)(n*pow(10,to)); 如果(检查器>=5){ dec++; } 四舍五入=(浮动)十二月/(功率(10到)); 返回(四舍五入); }
其他人指出,示例中的十进制值没有精确的二进制等价物

然后是三角洲:

  • 有一个十进制增量可能会打乱你的舍入,因为将一个不可表示的数字加到另一个数字上是不理想的
  • 增量应基于二进制值,其顺序为所显示数字的指数(单精度)的1/(2^23)或1/(2^52)(双精度)

  • 对于16Q范围内的单精度数字x:。。。将3.55转换为3.6,0.049999转换为0.0…?
    答:使用@Kninnug答案,但保留小数点后1位

    f = round(f * 10) / 10.0;
    
    它将为您提供
    3.5
    ,因为数字
    f
    最初不是3.55。确实,您使用文本“3.55”初始化了
    f
    ,但是
    C
    并且您的计算机无法准确表示该数字您的系统上没有(浮动)3.55。相反,
    f
    的值约为
    3.54999952…
    ,因为它是最接近的选择

    如果仍要将
    f
    四舍五入到3.6而不是3.5,则需要将
    f
    稍微向上推一点。当它是
    3.54999952…
    时,它的值>=3.55;当
    f
    0.049990016…
    (0.0499999也不完全可表示)时,相同的轻推使它保持
    f
    <0.5

    我们可以增加
    f
    的最小值是
    nextafterf(f,g)
    g
    是您希望向其移动的值

    3.549999952...   --> 3.550000190...
    0.04999990016... --> 0.04999990389...
    
    printf("%.1f\n", nextafterf(f, 2*f));
    // prints 3.6 when f is 3.549999952...
    // prints 0.0 when f is 0.04999990389...
    

    建议您查看@Oli Charlesworth答案中的参考资料

    在第二个示例中尝试此函数,您确定仅仅声明另一个变量就会改变
    printf()
    的行为吗?尝试添加所需精度的一半,例如
    f+0.05
    ,然后使用
    %.1f
    (或0.005和
    %.2f
    等)打印。顺便说一句,
    .1f
    打印
    .1f
    ,缺少
    %
    。如果在编译代码时启用警告,编译器会警告您缺少“%”。在带有gcc的Linux下,它打印了
    警告:格式[-Wformat extra args]的参数太多
    ,这一行显然有错误。输入要舍入的小数点523.567输入要舍入的小数点位数2舍入值为523.570007(这是我在上面程序中的输出,但我不确定后面的00007是从哪里来的,但你可以解决这个问题。无论如何,我使用的是Linux,你可能使用了其他操作系统)
    3.549999952...   --> 3.550000190...
    0.04999990016... --> 0.04999990389...
    
    printf("%.1f\n", nextafterf(f, 2*f));
    // prints 3.6 when f is 3.549999952...
    // prints 0.0 when f is 0.04999990389...