首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >四舍五入的正数,小数点半到2位,在C。

四舍五入的正数,小数点半到2位,在C。
EN

Stack Overflow用户
提问于 2014-08-03 12:59:06
回答 3查看 4K关注 0票数 6

通常,四舍五入到小数点2位是非常容易的

代码语言:javascript
复制
printf("%.2lf",<variable>);

然而,舍入系统通常会舍入到最接近的,甚至。例如,

代码语言:javascript
复制
2.554 -> 2.55
2.555 -> 2.56
2.565 -> 2.56
2.566 -> 2.57

我想要实现的是

代码语言:javascript
复制
2.555 -> 2.56
2.565 -> 2.57

实际上,舍入半向上的在C中是可行的,但只适用于整数;

代码语言:javascript
复制
int a = (int)(b+0.5)

因此,我要求如何做上面提到的同样的事情,在正值上小数点2位,而不是整数,以实现我前面所说的打印

EN

回答 3

Stack Overflow用户

发布于 2014-08-03 19:37:43

目前还不清楚你是否真的想要“四舍五入”,或者更确切地说是“从零到一半”,这就要求对负值进行不同的处理。

单精度二进制float精确到至少6位小数位,double精确到20位,因此DBL_EPSILON (在Float.h中定义)推到FP值将导致printf( "%.2lf", x )对n.nn5值的下一个100位。而不影响值的显示值,而不是n.nn5。

代码语言:javascript
复制
double x2  = x * (1 + DBL_EPSILON) ; // round half-away from zero
printf( "%.2lf", x2 ) ;

对于不同的四舍五入行为:

代码语言:javascript
复制
double x2  = x * (1 - DBL_EPSILON) ;  // round half-toward zero
double x2  = x + DBL_EPSILON ;        // round half-up
double x2  = x - DBL_EPSILON ;        // round half-down
票数 2
EN

Stack Overflow用户

发布于 2014-08-03 18:22:40

编辑OP澄清,只有打印值需要四舍五入到小数点2位。

OP认为数字的四舍五入是“半途而废”或“从零到零”或“远离零”,这是误导性的。在0.005,0.015,0.025,0.995等100个“中途”数字中,只有4个是典型的“中途”:0.125,0.375,0.625,0.875。这是因为浮点数格式使用基-2,而像2.565这样的数字不能精确表示.

相反,像2.565这样的示例数字作为假定binary642.564999999999999947...的最接近的double值。将这一数字相加到最近的0.01应该是2.56,而不是执行部分所希望的2.57。

因此,只有数字以0.125和0.625的面积结束,正好是一半,并且是四舍五入,而不是像OP所期望的那样上升。建议接受并使用:

代码语言:javascript
复制
printf("%.2lf",variable);  // This should be sufficient

为了接近OP的目标,数字可能会被A(以0.125或0.625或B结尾)测试)略有增加。最小的增长将是

代码语言:javascript
复制
#include <math.h>
printf("%.2f", nextafter(x, 2*x));

在@Clifford中还发现了另一种推拿方法。

前一个答案将一个double舍入到最近的double倍数为0.01。

典型的浮点格式使用像binary64这样的格式,它使用基-2。“四舍五入到最近的数学0.01,并与0.0相加”是一项挑战。

正如@Pascal所提到的,像2.555这样的浮点数通常只在2.555附近,并且有一个更精确的值,比如2.555000000000000159872...,而不是半途而废。

@BLUEPIXY解决方案是最好和实用的。

代码语言:javascript
复制
x = round(100.0*x)/100.0;

圆周函数以浮点格式将其参数绕到最近的整数值,将大小写与零相舍五入,而不考虑当前的舍入方向。C11dr§7.12.9.6.

((int)(100 * (x + 0.005)) / 100.0)方法有两个问题:对于负数(OP没有指定),它可能绕错方向,整数的范围通常比double小得多(INT_MININT_MAX)。

在某些情况下,比如当double x = atof("1.115");接近1.12时,它实际上应该是1.11,因为作为doubledouble确实更接近1.11,而不是“半途而废”。

代码语言:javascript
复制
string   x                         rounded x 
1.115 1.1149999999999999911182e+00 1.1200000000000001065814e+00

假设为y = -f(-x),OP没有指定负数的舍入。

票数 1
EN

Stack Overflow用户

发布于 2014-08-03 23:51:27

下面是将double舍入最近的0.01 double的精确代码。

x = round(100.0*x)/100.0;这样的代码函数,除了处理使用操作以确保精确地完成100.0的缩放之外,还没有造成精度损失。

这可能是比OP感兴趣的代码更多的代码,但它确实有效。

它适用于整个double范围-DBL_MAXDBL_MAX。(仍然应该做更多的单元测试)。

它依赖于FLT_RADIX == 2,这是很常见的。

代码语言:javascript
复制
#include <float.h>
#include <math.h>

void r100_best(const char *s) {
  double x;
  sscanf(s, "%lf", &x);

  // Break x into whole number and fractional parts.  
  // Code only needs to round the fractional part.  
  // This preserves the entire `double` range.
  double xi, xf;
  xf = modf(x, &xi);

  // Multiply the fractional part by N (256). 
  // Break into whole and fractional parts.
  // This provides the needed extended precision.
  // N should be >= 100 and a power of 2.
  // The multiplication by a power of 2 will not introduce any rounding.
  double xfi, xff;
  xff = modf(xf * 256, &xfi);

  // Multiply both parts by 100.  
  // *100 incurs 7 more bits of precision of which the preceding code
  //   insures the 8 LSbit of xfi, xff are zero.
  int xfi100, xff100;
  xfi100 = (int) (xfi * 100.0);
  xff100 = (int) (xff * 100.0); // Cast here will truncate (towards 0)

  // sum the 2 parts.  
  // sum is the exact truncate-toward-0 version of xf*256*100
  int sum = xfi100 + xff100;
  // add in half N
  if (sum < 0)
    sum -= 128;
  else
    sum += 128;

  xf = sum / 256;
  xf /= 100;
  double y = xi + xf;
  printf("%6s %25.22f ", "x", x);
  printf("%6s %25.22f %.2f\n", "y", y, y);
}

int main(void) {
  r100_best("1.105");
  r100_best("1.115");
  r100_best("1.125");
  r100_best("1.135");
  r100_best("1.145");
  r100_best("1.155");
  r100_best("1.165");
  return 0;
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25104883

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档