如何通过在C中作为int转换来舍入浮点数

问题描述 投票:2回答:5

所以我是大学第二学期的新生。我的老师希望我们编写一个将浮点数舍入到最近的百分之一的函数。他说我们需要将浮点数转换为整数数据类型,然后将其转换回浮点数。这就是他所说的。我花了至少5个小时尝试不同的方法来做到这一点。

到目前为止这是我的代码:

#include <stdio.h>

int rounding(int roundedNum);
int main()
{
   float userNum,
         rounded;

   printf("\nThis program will round a number to the nearest hundredths\n");
   printf("\nPlease enter the number you want rounded\n>");

   scanf("%f", &userNum);

   rounded = rounding (userNum);

   printf("%f rounded is %f\n", userNum, rounded);

   return 0;
}

int rounding(int roundedNum)
{


   return roundedNum;
}
c c99
5个回答
2
投票

你的导师可能在想:

float RoundHundredth(float x)
{
    // Scale the hundredths place to the integer place.
    float y = x * 100;

    // Add .5 to cause rounding when converting to an integer.
    y += .5f;

    // Convert to an integer, which truncates.
    int n = y;

    // Convert back to float, undo scaling, and return.

    return n / 100.f;
}

这是一个有缺陷的解决方案,因为:

  • 大多数C实现使用二进制浮点。在二进制浮点中,不可能存储任何不是2的负幂的倍数的分数(½,¼,⅛,1 / 16,1 / 32,1 / 64,......)。所以1/100无法准确表示。因此,无论你做什么计算,都不可能准确地返回.01或.79。你能做的最好就是靠近。
  • 对浮点数执行算术运算时,结果将四舍五入为最接近的可表示值。这意味着,在x * 100中,结果通常不是x的100倍。由于四舍五入,存在一个小错误。此错误会导致值越过圆形从一个方向变为另一个方向的点,因此它可能使答案错误。有一些技术可以避免这种错误,但它们对于入门课程来说太复杂了。
  • 无需转换为整数即可进行截断; C具有浮点内置的截断函数:truncdoubletruncffloat
  • 此外,在转换为整数时使用截断迫使我们添加½以获得舍入。但是,一旦我们不再使用转换为整数类型来获取整数值,我们就可以使用内置函数将浮点值舍入为整数值:rounddoubleroundffloat

如果你的C实现具有良好的格式化输入/输出例程,那么找到舍入到最接近的百位的浮点数值的简单方法是使用转换说明符snprintf对其进行格式化(与%.2f一样)。一个正确的C实现将数字转换为十进制,小数点后面有两位数,使用正确的舍入,避免上面提到的算术舍入错误。但是,您将获得字符串形式的数字。


0
投票

以下是一些提示:

  1. 乘以“一些10的幂”浮动,以确保所需的精度数字向左移动
  2. 将新值转换为新的int变量,以便丢弃不需要的浮点数
  3. 将int除以10的相同幂,但添加使用浮点形式(例如10.0),因此整数转换为float,新值是正确的值
  4. 要测试,请使用精度为(.2f)的printf

0
投票

四种最常见的舍入方法是“远离零”和“银行家舍入(均匀)”。

用于舍入零的伪代码

编辑即使这是伪代码,我应该包括精度的计算,因为我们在这里处理浮点值。

// this code is fixed for 2 decimal places (n = 2) and
// an expected precision limit of 0.001 (m = 3)
// for any values of n and m, the first multiplicand is 10^(n+1)
// the first divisor is 10^(m + 1), and
// the final divisor is 10^(n)

double roundAwayFromZero(double value) {
  boolean check to see if value is a negative number
  add precision bumper of (1.0 / 10000) to "value" // 10000.0 is 10^4
  multiply "value" by 1000.0 and cast to (int)  // 1000.0 is 10^3
  if boolean check is true, negate the integer to positive
  add 5 to integer result, and divide by 10
  if boolean check is true, negate the integer again
  divide the integer by 100.0 and return as double  // 100.0 is 10^2

  ex: -123.456
      true
      -123.456 + (1.0 / 10000.0) => -123.4561
      -123.4561 * 1000.0 => -123456.1 => -123456 as integer
      true, so => -(-123456) => 123456
      (123456 + 5) / 10 => 123461 / 10 => 12346
      true, so => -(12346) => -12346
      -12346 / 100.0 => -123.46 ===> return value
}

在您的初始问题中,您表达了对方向的渴望,而不是代码中的明确答案。这是模糊的,因为我可以设法做到它同时仍然有任何意义。我将留下“银行家的舍入”版本供您实施作为练习。


0
投票

好的,我明白了!谢谢你的回答。

//function
float rounding(float roundedNumber)
{
   roundedNumber = roundedNumber * 100.0f + 0.5f;
   roundedNumber = (int) roundedNumber * 0.01f;

   return roundedNumber;
}

所以,如果我输入56.12567作为roundNumber,它将乘以100,得到5612.567。从那里它将添加.5,这将决定它是否向上舍入。在这种情况下,确实如此。该数字将更改为5613.067。然后通过将其转换为int并将其乘以.01来截断它以获得小数。从那里它将值返回到main并打印出舍入的数字。很奇怪的舍入方式,但我猜你是如何在不使用舍入功能的情况下在C中完成的。


-1
投票

好吧,让我们考虑一下。有一点值得知道的是我们可以通过强制转换将float转换为整数:

float x = 5.4;
int y = (int) x;
//y is now equal to 5

当我们进行转换时,浮动被截断,这意味着无论其值如何(即它始终向0舍入),小数点之后的任何内容都将被删除。

因此,如果您考虑到这一点以及您关心百分之一的事实,您可以想象一种方法,包括在某种程度上操纵浮点数,这样当您将其转换为int时,您只会截断不是关心(即数字超过百分之一的地方)。乘法可能在这里很有用。

© www.soinside.com 2019 - 2024. All rights reserved.