【问题标题】:Function that reverse one part(half) of integer反转整数的一部分(一半)的函数
【发布时间】:2020-02-02 12:53:04
【问题描述】:

我想写一个函数来反转数字的两个部分之一:

输入是:num = 1234567; part = 2 输出为:1234765

所以这里是 part 只能是 1 或 2

现在我知道如何获得第 1 部分

int firstPartOfInt(int num) {
    int ret = num;
    digits = 1, halfDig = 10;
    while (num > 9) {
        ret = ret / 10;
        digits++;
    }
    halfDigits = digits / 2;
    for (int i = 1; i < halfDigits; i++) {
        halfDigits *= 10;
    }
    ret = num;
    while (num > halfDigits) {
        ret = ret / 10;
    }
    return ret;
}

但我不知道如何获取第 2 部分并反转数字。如果您在此处发布代码,请不要使用vector&lt;&gt; 和其他与 C 不兼容的 C++ 功能

【问题讨论】:

  • 如果你在这里发布代码,请不要使用vector和其他与C不兼容的特性;修复您的标签并让我们知道您使用 C 还是 C++ 会很有帮助。
  • 我使用 C++,但我不喜欢容器(字符串除外)和模板
  • @ReQserFirFir 我写了一个答案。请让我知道你的想法。如果符合您的要求,请点赞并采纳。如果没有,请给我一些反馈
  • other C++ feature not compatible with C C 特性与 C++ 不兼容怎么办? here is part that can be only 1 or 2 - 那么为什么你的函数只接受一个参数,而不是两个呢?为什么只有最后 3 位数字是倒置的,而不是像 6 位数字?什么是“第 1 部分”/“第 2 部分”?就return num % 1000 + num % 10 * 100 + num / 10 % 10 * 10 + num / 100 % 10?
  • @KamilCuk 我需要只反转数字的一半的函数,第一个或第二个数字可以是 7 位、100 位甚至 2。我的函数从数字返回前半部分。示例:输入 12345 输出 123

标签: c++ c


【解决方案1】:

一种方法是计算数字中的总位数,然后按照一定的顺序从原始数字中提取数字,计算一个新的数字,复杂度O(number-of-digits):

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

unsigned reverse_decimal_half(unsigned n, unsigned half) {
    unsigned char digits[sizeof(n) * 3];
    unsigned digits10 = 0;
    do digits[digits10++] = n % 10;
    while(n /= 10);
    unsigned result = 0;
    switch(half) {
    case 1:
        for(unsigned digit = digits10 / 2; digit < digits10; ++digit)
            result = result * 10 + digits[digit];
        for(unsigned digit = digits10 / 2; digit--;)
            result = result * 10 + digits[digit];
        break;
    case 2:
        for(unsigned digit = digits10; digit-- > digits10 / 2;)
            result = result * 10 + digits[digit];
        for(unsigned digit = 0; digit < digits10 / 2; ++digit)
            result = result * 10 + digits[digit];
        break;
    default:
        abort();
    }
    return result;
}

int main() {
    printf("%u %u %u\n", 0, 1, reverse_decimal_half(0, 1));
    printf("%u %u %u\n", 12345678, 1, reverse_decimal_half(12345678, 1));
    printf("%u %u %u\n", 12345678, 2, reverse_decimal_half(12345678, 2));
    printf("%u %u %u\n", 123456789, 1, reverse_decimal_half(123456789, 1));
    printf("%u %u %u\n", 123456789, 2, reverse_decimal_half(123456789, 2));
}

输出:

0 1 0
12345678 1 43215678
12345678 2 12348765
123456789 1 543216789
123456789 2 123459876

【讨论】:

    【解决方案2】:

    如果很好理解这个问题,你需要将小数的一半取反。如果数字有奇数位数,我假设第一部分更长(例如 12345 - 第一部分是 123,第二部分是 45)。因为反向是人工的,所以 52001234 的第 1 部分是 521234

    https://godbolt.org/z/frXvCM (某些数字在反转时可能会环绕 - 未检查)

    int getndigits(unsigned number)
    {
        int ndigits = 0;
        while(number)
        {
            ndigits++;
            number /= 10;
        }
        return ndigits;
    }
    
    unsigned reverse(unsigned val, int ndigits)
    {
        unsigned left = 1, right = 1, result = 0;
    
        while(--ndigits) left *= 10;
        while(left)
        {
            result += (val / left) * right;
            right *= 10;
            val = val % left;
            left /= 10;
        }
        return result;
    }
    
    unsigned reversehalf(unsigned val, int part)
    {
        int ndigits = getndigits(val);
        unsigned parts[2], digits[2], left = 1;
    
        if(ndigits < 3 || (ndigits == 3 && part == 2))
        {
            return val;
        }
    
        digits[0] = digits[1] = ndigits / 2;
        if(digits[0] + digits[1] < ndigits) digits[0]++;
        for(int dig = 0; dig < digits[1]; dig++) left *= 10;
    
        parts[0] = val / left;
        parts[1] = val % left;
    
        parts[part - 1] = reverse(parts[part - 1], digits[part - 1]);
        val = parts[0] * left + parts[1];
    
        return val;
    }
    
    int main()
    {
        for(int number = 0; number < 40; number++)
        {
            unsigned num = rand();
            printf("%u \tpart:%d\trev:%u\n", num,(number & 1) + 1,reversehalf(num, (number & 1) + 1));
        }
    }
    

    【讨论】:

      【解决方案3】:

      我的五分钱。:)

      #include <iostream>
      
      int reverse_part_of_integer( int value, bool first_part = false )
      {
          const int Base = 10;
      
          size_t n = 0;
      
          int tmp = value;
      
          do
          {
              ++n;        
          } while ( tmp /= Base );
      
          if ( first_part && n - n / 2 > 1 || !first_part && n / 2 > 1 )
          {
              n = n / 2;
              int divider = 1;
      
              while ( n-- ) divider *= Base;
      
              int first_half  = value / divider;
              int second_half = value % divider;
      
              int tmp = first_part ? first_half : second_half;
      
              value = 0;
      
              do
              {
                  value = Base * value + tmp % Base;
              } while ( tmp /= Base );
      
              value = first_part ? value * divider + second_half
                                 : first_half * divider +value;
          }
      
          return value;
      }
      
      
      int main() 
      {
          int value = -123456789;
      
          std::cout << "initial value:        " 
                    << value << '\n';
      
          std::cout << "First part reversed:  " 
                    << reverse_part_of_integer( value, true ) << '\n';
      
          std::cout << "Second part reversed: " 
                    << reverse_part_of_integer( value ) << '\n';
      }
      

      程序输出是

      initial value:        -123456789
      First part reversed:  -543216789
      Second part reversed: -123459876
      

      【讨论】:

      • @P__J__ 该函数没有使用 C++ 的任何 C 中不存在的特性。所以你的评论没有意义。
      • @P__J__ 您也可以在 C 中使用此名称。包含相应的标题就足够了。而且它不是 C++ 类。
      【解决方案4】:

      只是为了好玩,一个在反转之前只计算一半位数的解决方案:

      constexpr int base{10};
      
      constexpr int partial_reverse(int number, int part)
      {
          // Split the number finding its "halfway"
          int multiplier = base;
          int abs_number = number < 0 ? -number : number;
          int parts[2] = {0, abs_number};
          while (parts[1] >= multiplier)
          {
              multiplier *= base;
              parts[1] /= base;
          }
          multiplier /= base;    
          parts[0] = abs_number % multiplier;
      
          // Now reverse only one of the two parts
          int tmp = parts[part];
          parts[part] = 0;
          while (tmp)
          {
              parts[part] = parts[part] * base + tmp % base;
              tmp /= base;
          }
      
          // Then rebuild the number
          int reversed = parts[0] + multiplier * parts[1];
          return number < 0 ? -reversed : reversed;
      }
      
      int main()
      {
          static_assert(partial_reverse(123, 0) == 123);
          static_assert(partial_reverse(-123, 1) == -213);
          static_assert(partial_reverse(1000, 0) == 1000);
          static_assert(partial_reverse(1009, 1) == 109);
      
          static_assert(partial_reverse(123456, 0) == 123654);
          static_assert(partial_reverse(1234567, 0) == 1234765);
          static_assert(partial_reverse(-1234567, 1) == -4321567);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-05-11
        • 1970-01-01
        • 2021-07-12
        • 1970-01-01
        • 2017-02-08
        • 1970-01-01
        • 2022-07-11
        • 1970-01-01
        相关资源
        最近更新 更多