为什么最终输出自行舍入?

发布于 2025-02-05 00:35:37 字数 647 浏览 1 评论 0原文

在下面的代码中,

  #include< stdio.h>

    浮子区域(浮动VAR)
    {
        返回(var*var);
    }

    int main()
    {
       浮动一侧;
       printf(“ \ nenter在广场的侧面:”);
       scanf(“%f”,& side);

       ** printf(“区域为:%.1f”,区域(侧)); **

       返回0;
    }
 

输入为15.5,如果使用格式“%.1F”,则输出为:

240.3

以及何时,
输入为15.5,格式指定符“%.2F”,然后输出为:

240.25(实际上是正确的值)



Why does the value gets rounded off when format specifier is "%.1f", instead of just printing upto the first decimal place and the output being 240.2 ?

In the code below,

    #include <stdio.h>

    float area(float var)
    {
        return (var*var);
    }

    int main()
    {
       float side;
       printf("\nEnter the side of square : ");
       scanf("%f",&side);

       **printf("The area is : %.1f",area(side));**

       return 0;
    }

Input is 15.5, if format specifier "%.1f" is used then the output is:

240.3

and when,
Input is 15.5, with format specifier "%.2f" then the output is :

240.25 (which is actually the correct value)

Why does the value gets rounded off when format specifier is "%.1f", instead of just printing upto the first decimal place and the output being 240.2 ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

依 靠 2025-02-12 00:35:38

规格要求四舍五入。 f格式指定符,C17规格说

a double 代表浮点数的参数转换为样式 [ - ] ddd.ddd 中的十进制表示法,其中十位后数字数字的数量点字符等于精度规范。如果缺少精度,则将其视为6;如果精度为零并且未指定#标志,则不会出现小数点字符。如果出现小数点字符,则至少在其之前出现一个数字。该值舍入到适当数量的数字。

注意最后一句话。

现在,有多种舍入的方式。我认为printf被指示旨在纪念 fesetround ,这在我的系统上也不例外。

#include <fenv.h>
#include <stdio.h>

// gcc doesn't recognize or need this.
#pragma STDC FENV_ACCESS ON

int main( void ) {
   fesetround( FE_DOWNWARD );
   printf( "%.1f\n", 0.66 );   // 0.6

   fesetround( FE_TONEAREST );
   printf( "%.1f\n", 0.66 );   // 0.7
}

demo 在编译器资源管理器上,


我的系统默认值default to found to found。当它需要选择两个数字中的哪个最接近(例如0.5)时,它圆满到最接近的数字。

#include <stdio.h>

int main( void ) {
   printf( "%.0f\n", 0.5 );  // 0
   printf( "%.0f\n", 1.5 );  // 2
   printf( "%.0f\n", 2.5 );  // 2
   printf( "%.0f\n", 3.5 );  // 4
   printf( "%.0f\n", 4.5 );  // 4
}

demo 在编译器资源管理器

上因为5/10可以由浮点数准确表示。)


我不知道规格是否要求默认为四舍五入到最接近,但这是自然而然的事情数字中的十进制位置。

如果不这样做,它也会产生很多奇怪的结果。您是否期望printf(“%.1f \ n”,0.3);打印0.2?好吧,如果您舍入而不是四舍五入到最近。

二进制中的数字是周期性的,包括1/10、2/10、3/10、4/10、6/10、7/10、7/10、8/10和9/10。这些不能完全使用浮点号来准确表示。理想情况下,编译器使用最近的代表数字,有时该数字有时更高,有时稍低一些。

#include <stdio.h>

int main( void ) {
   printf( "%.100g\n", 0.1 );  // 0.1000000000000000055511151231257827021181583404541015625
   printf( "%.100g\n", 0.3 );  // 0.299999999999999988897769753748434595763683319091796875
}

demo 在编译器资源管理器上,

如果printf是truncate,printf(printf)(printf(printf)( “%.1f \ n”,0.3);将打印0.2

#include <fenv.h>
#include <stdio.h>

// gcc doesn't recognize or need this.
#pragma STDC FENV_ACCESS ON

int main( void ) {
   fesetround( FE_DOWNWARD );
   printf( "%.1f\n", 0.3 );   // 0.2

   fesetround( FE_TONEAREST );
   printf( "%.1f\n", 0.3 );   // 0.3
}

demo 在编译器资源管理器上


,最后我找不到有关如何四舍五入到最近的规格中的任何东西。甚至可以回合的决定似乎是编译器的决定。

这条打题规则没有正/负偏见,也没有偏见/远离零的偏见,这使其自然而然。它甚至是“ IEEE 754操作中使用的默认舍入模式,用于二进制浮点格式的结果”。

The spec mandates rounding. Of the f format specifier, the C17 spec says

A double argument representing a floating-point number is converted to decimal notation in the style [-]ddd.ddd, where the number of digits after the decimal-point character is equal to the precision specification. If the precision is missing, it is taken as 6; if the precision is zero and the # flag is not specified, no decimal-point character appears. If a decimal-point character appears, at least one digit appears before it. The value is rounded to the appropriate number of digits.

Note the last sentence.

Now, there are many ways of rounding. I think printf is directed to honour the "directed rounding mode" set by fesetround, and it's no exception on my system.

#include <fenv.h>
#include <stdio.h>

// gcc doesn't recognize or need this.
#pragma STDC FENV_ACCESS ON

int main( void ) {
   fesetround( FE_DOWNWARD );
   printf( "%.1f\n", 0.66 );   // 0.6

   fesetround( FE_TONEAREST );
   printf( "%.1f\n", 0.66 );   // 0.7
}

Demo on Compiler Explorer


My system defaults to rounding to nearest. When it needs to choose which of two numbers are nearest (e.g. for 0.5), it rounds to nearest even number.

#include <stdio.h>

int main( void ) {
   printf( "%.0f\n", 0.5 );  // 0
   printf( "%.0f\n", 1.5 );  // 2
   printf( "%.0f\n", 2.5 );  // 2
   printf( "%.0f\n", 3.5 );  // 4
   printf( "%.0f\n", 4.5 );  // 4
}

Demo on Compiler Explorer

(I used .0f and .5 since 5/10 can be represented exactly by a floating point number.)


I don't know if the spec mandates defaulting to round to nearest or not, but that's the natural thing to do when one wants to reduce the number of decimal places in a number.

It would also produce a lot of weird results if it didn't do this. Would you expect printf( "%.1f\n", 0.3 ); to print 0.2? Well, it would if you rounded down instead of rounding to nearest.

So many number are periodic in binary, including 1/10, 2/10, 3/10, 4/10, 6/10, 7/10, 8/10 and 9/10. These can't be represented exactly using floating point numbers. Ideally, the compiler uses the nearest representable number instead, and this number is sometimes a little higher, sometimes a little lower.

#include <stdio.h>

int main( void ) {
   printf( "%.100g\n", 0.1 );  // 0.1000000000000000055511151231257827021181583404541015625
   printf( "%.100g\n", 0.3 );  // 0.299999999999999988897769753748434595763683319091796875
}

Demo on Compiler Explorer

If printf were to truncate, printf( "%.1f\n", 0.3 ); would print 0.2.

#include <fenv.h>
#include <stdio.h>

// gcc doesn't recognize or need this.
#pragma STDC FENV_ACCESS ON

int main( void ) {
   fesetround( FE_DOWNWARD );
   printf( "%.1f\n", 0.3 );   // 0.2

   fesetround( FE_TONEAREST );
   printf( "%.1f\n", 0.3 );   // 0.3
}

Demo on Compiler Explorer


Finally, I don't find anything in the spec about how to round to nearest. The decision to round to even appears to be the compiler's.

This tie-breaking rule has no positive/negative bias and no bias toward/away from zero, making it a natural choice. It's even "the default rounding mode used in IEEE 754 operations for results in binary floating-point formats."

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文