【问题标题】:Rounding integers to nearest ten or hundred in C在C中将整数四舍五入到最接近的十或百
【发布时间】:2013-01-15 18:54:12
【问题描述】:

我试图在 C 中考虑一个满足以下条件的函数:

  • 它接受大于 0 的整数作为参数;
  • 它将整数向上舍入到最接近的值,这样只有第一个 数字不是零

例如:

53 变成 60..

197 变成 200..

4937 输出为 5000..

有没有办法做到这一点,无论尾随零的数量如何都能满足要求?

例如,我了解在任何个别情况下我如何做到这一点。 divide 53 by 10 then ceil(), multiply by 10, 但我想要一个可以处理任何值的。

意见?想法?

【问题讨论】:

  • 将 int 解析为字符串,将 int 除以 10 *(字符串长度减 1),将其设置为 ceil 并乘以除法器。这行得通吗?
  • 我实际上是指幂,而不是乘法,但我会投票支持对数解决方案。

标签: c rounding


【解决方案1】:

避免字符串转换和循环:

int num = ... // your number
int len = log10(num);
float div = pow(10, len);
int rounded = ceil(num / div) * div;

【讨论】:

    【解决方案2】:

    没有必要将数字转换为字符串并返回。您可以使用基本的模算术和乘除法来做到这一点。

    这是一个纯数字解决方案,希望在运行时间方面更有效:

    int round_up_to_max_pow10(int n)
    {
        int tmp = n;
        int i = 0;
        while ((tmp /= 10) >= 10) {
            i++;
        }
    
        if (n % (int)(pow(10, i + 1) + 0.5)) {
            tmp++;
        }
    
        for (; i >= 0; i--) {
            tmp *= 10;
        }
    
        return tmp;
    }
    
    printf("Original: %d; rounded: %d\n", 4937, round_up_to_max_pow10(4937));
    

    【讨论】:

    • +1 同意!转换成字符串/从字符串转换是昂贵且笨拙的。这是一道数学题,应该这样对待。
    • 这会将 2445 舍入为 3000。
    • @Guffa 是的,正如预期的那样。
    • @Guffa - 不幸的是,OP 使用“圆形”作为“天花板”的同义词。后者似乎是 OP 的意图。
    • @Guffa 正如 OP 所说:“它将整数 up 舍入到最接近的值,以便只有第一个数字不是零”。
    【解决方案3】:

    在这里,对数非常有用,可以为“这有多少个零?”提供恒定时间的答案

    floor(log10(x))= z //the number of zeros
    

    将采用以 10 为底的对数,并为您提供 x 中零的数量。

    然后你可以使用 C 的偶然习语

    (A+B-1)/B

    快速找到 A/B 的上限,以这种方式得出正确的前导数:

    zeros = exp10(1,z);
    ((x+zeros-1)/zeros) * zeros
    

    这是伪代码,但你应该明白。关键的理解是对数是在数学上确定一个数字有多少位数的方法。

    【讨论】:

      【解决方案4】:

      通过 Cocoa API:

      int number=9435;
      NSString *string=[NSString stringWithFormat:@"%d",number];
      long length=[string length];    
      NSString *roundedString=[NSString stringWithFormat:@"%d",([[string substringToIndex:1]intValue]+1)];
      while (--length>0) {
          roundedString=[roundedString stringByAppendingString:@"0"];
      }
      int roundedNumber=[roundedString intValue];
      NSLog(@"%d,   %d",number,roundedNumber);
      

      按照典型的 C 风格,数学上:

      int i=8517;
      
      int temp=i;
      int len,msb;
      
      for (len=0; temp>0; len++) {
          msb=temp;
          temp/=10;
      }
      msb++;
      int multiplier=1;
      for (int i=1; i<len; i++) {
          multiplier*=10;
      }
       NSLog(@"Rounded : %d",msb*multiplier);
      

      【讨论】:

      • 我看了几十个答案,即使我能解决这个初中的问题,我也很想解决这个问题......但是使用很少的可可API可以很容易地解决这个问题......: D
      • 为时已晚,但增加了一种使用可可字符串的方法
      • 我不认为这对 Cocoa 或 Objective-C 来说是个好广告;-) 不可读。问题标记为 C。
      • @Clifford:他已经编辑了这个问题,之前它被标记为 ios、cocoa、obj-c。
      • @AnoopVaidya:抱歉。
      【解决方案5】:

      我不确定你想要圆形还是 ceil。但是您在问题中表现出的行为暗示了 ceil。所以我把它包括在内。

      int my_ceil(int num)
      {
          int den = 1;
          int inc = 0;
      
          while (num >= 10) {
              inc += num % 10;
              num /= 10;
              den *= 10;
          }
      
          return (num + (inc > 0)) * den;
      }
      

      编辑

      更改代码以删除 ceil 和其他额外操作。

      编辑 2

      固定为 10 的倍数。

      【讨论】:

      • 不适用于某些数字。如果数字是9,结果是10,如果数字是10,结果是11...
      • @Guffa 你说得对,它不适用于任何 10 的倍数。我想我现在修好了。
      • @Guffa 它产生 10 而不是 180。错过了括号。
      • 工作,但由于声明的放置需要 C99 或 C++ 编译。
      • @Clifford 旧习惯 :)。取出 if 条件应该可以解决问题。这不是绝对必要的。
      【解决方案6】:

      尝试取输入数字的第一个字符,加 1,然后附加零。

          Dim Input = "23568"
          Dim roundUp = Left(Input, 1) + 1
      
          For x = 1 To Len(Input) - 1
              roundUp &= "0"
          Next
      

      在 VB 中,但希望你能明白。

      【讨论】:

      • 这被标记为 C,而不是 VB。
      • 因此我写了“在 VB 中,但希望你能明白”。这个概念仍然适用。
      • 如果输入是200,输出应该是200的时候是300。
      【解决方案7】:

      我会将数字转换为字符串。获取字符串的长度。

      然后:

      // pseudo code:
      divisor = pow(10, len of number string)
      answer = ceil (number/divisor) * divisor;
      

      【讨论】:

      • 语法不好,但表达了概念。 +1。
      • 在数学上十进制位数是floor(log10(n) + 1))或更简单的(int)(log10(m) + 1) - 不需要字符串转换。
      【解决方案8】:

      你可以把这个数除以十,直到只剩下一位数,然后再乘回到大小:

      int n = 4937;
      
      int m = 1;
      while (n >= 10) {
        n = (n + 9) / 10;
        m *= 10;
      }
      n *= m;
      

      【讨论】:

        【解决方案9】:

        应该这样做:

        static int
        rnd_up(int val)
        {
            double e, r;
        
            e = exp10(trunc(log10((double)val)));
            r = round(((double)val / e) + 0.5);
        
            return(r * e);
        }
        

        【讨论】:

        • 可能值得注意的是,exp10(n) 是相当于pow(10,n) 的 GNU 库扩展
        • trunc() 和 round() 也不是标准的
        • 使用 _GNU_SOURCE 和 math.h 在标准 linux 上编译。我没有看到使用任何特定子集解决问题的请求。
        • 确实,我只是为任何对它很重要的人指出了这一点。在这种情况下,我测试了许多发布的看起来更合理的解决方案,但您的解决方案我无法使用 VC++ 进行测试。我认为缺乏目标规范意味着需要尽可能广泛的适用性,而不是强制缩小解决方案。
        • 我的目标不是解决编译代码的实际问题,这就是为什么我没有提供整个程序,尽管我有一个。我的目标是证明数学相当简单,例如可以在标准 Linux 系统上完成。
        【解决方案10】:

        没有循环。

        #include <math.h>
        unsigned roundToNextExp10( unsigned a )
        {
            int d = a ;
            if( a >= 10 )
            {
                int m ;
                d-- ;
                m = (int)pow( 10, ((int)log10(d)) ) ;
                d = (int)((d / m) + 1) * m ;
            }        
            return d ;
        }
        

        【讨论】:

          【解决方案11】:
          /*-------------------------------------------------*/
          /* Round up a number                               */
          /* (Negative numbers go DOWN)                      */
          /* 34 -> 40                                        */
          /* -34 -> -40                                      */
          /*-------------------------------------------------*/
          int round_up_10(int num) 
          {
              int sign = 1;
              int tens = 1;
          
              if (num < 0)
              {
                  num = (-1) * num;
                  sign = -1;
              }
              num = (num + 9) / 10;
              num = num * 10;
          
              return sign * num;
          }
          /*-------------------------------------------------*/
          /* Round down a number                             */
          /* (Negative numbers go UP)                        */
          /* 34 -> 30                                        */
          /* -34 -> -30                                      */
          /*-------------------------------------------------*/
          int round_down_10(int num)   
          {
              int sign = 1;
              int tens = 1;
          
              if (num < 0)
              {
                  num = (-1) * num;
                  sign = -1;
              }
              num = num / 10;
              num = num * 10;
          
              return sign * num;
          }
          
          main()
          {
              printf("round_down_10(25450)= %d\n", round_down_10(25450));
              printf("round_down_10(-25450)= %d\n", round_down_10(-25450));
              printf("round_up_10(25450)= %d\n", round_up_10(25450));
              printf("round_up_10(-25450)= %d\n", round_up_10(-25450));
          
              printf("round_down_10(1347)= %d\n", round_down_10(1347));
              printf("round_down_10(-1347)= %d\n", round_down_10(-1347));
              printf("round_up_10(1347)= %d\n", round_up_10(1347));
              printf("round_up_10(-1347)= %d\n", round_up_10(-1347));
          
              printf("round_down_10(34)= %d\n", round_down_10(34));
              printf("round_down_10(-34)= %d\n", round_down_10(-34));
              printf("round_up_10(34)= %d\n", round_up_10(34));
              printf("round_up_10(-34)= %d\n", round_up_10(-34));
          }
              /*
              The outout:
              round_down_10(25450)= 25450
              round_down_10(-25450)= -25450
              round_up_10(25450)= 25450
              round_up_10(-25450)= -25450
              round_down_10(1347)= 1340
              round_down_10(-1347)= -1340
              round_up_10(1347)= 1350
              round_up_10(-1347)= -1350
              round_down_10(34)= 30
              round_down_10(-34)= -30
              round_up_10(34)= 40
              round_up_10(-34)= -40
              */
          

          【讨论】:

          • 这似乎不满足 OP 中提出的条件 - “有没有办法做到这一点,无论尾随零的数量如何都能满足要求?”
          【解决方案12】:

          您可以在这里获得一些专家建议...将数字 i 舍入到最接近的 10:

          if (i%10)
             i += 10 - i%10;    
          

          同样适用于 100s、1000s 等

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-03-21
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多