【问题标题】:Circular shift Int32 digits using C#使用 C# 循环移位 Int32 数字
【发布时间】:2015-07-01 17:46:42
【问题描述】:

会员,

我要做的是右移或左移Int32 的数字(不是位!!)。

所以如果改变常数:

123456789

3

我应该得到

789123456

所以没有数字会丢失,因为我们谈论的是循环移位。 经过一番测试,我想出了这个方法,它有效:

static uint[] Pow10 = new uint[] { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, uint.MaxValue };
    static uint RotateShift10(uint value, int shift)
    {
        int r = (int)Math.Floor(Math.Log10(value) + 1);
        while (r < shift)
            shift = shift - r;
        if (shift < 0) shift = 9 + shift;
        uint x = value / Pow10[shift];
        uint i = 0;
        while (true)
        {
            if (x < Pow10[i])
                return x + (value % Pow10[shift]) * Pow10[i];
            i += 1;
        }
    }

我正在寻找的方式应该是算术解决方案,而不是字符串转换然后旋转。 我还假设:

  • Int32 值中没有 0 位数字,以防止任何数字丢失。
  • Int32 是一个非负数
  • 一个正的 Rotation 整数应该向右移动,负一个向左移动。

我的算法已经完成了所有这些,我想知道是否有办法对其进行微调,是否有更好的算法解决方案?

【问题讨论】:

  • 并非所有数字都可以这样旋转(考虑 1173741829 向右旋转 1 个位置,90 亿对于 int 来说太大了),它们呢?我们应该假设这不会发生吗?
  • @harold :是的,我认为这样的溢出不会发生,因为输入会更小;)
  • @dark 你的方法抛出shift = 0,也可以用uint.MaxValue试试,它会给出一个无效的答案。

标签: c# int32


【解决方案1】:

因为我无法抗拒“必须采用算术方法”的挑战:D,所以摆弄了以下内容:

    static uint RotateShift(uint value, int shift)
    {
        int len = (int)Math.Log10(value) + 1;
        shift %= len;
        if (shift < 0) shift += len;            
        uint pow = (uint)Math.Pow(10, shift);
        return (value % pow) * (uint)Math.Pow(10, len - shift) + value / pow;
    }

编辑还有一些测试结果

foreach(var val in new uint[]{123456789, 12345678})
   foreach (var shift in new[] { 3, -3, 1, -1, 11, -11, 18 })
   {
      Console.WriteLine("Value {0} Shift {1} -> {2}", val, shift, RotateShift(val, shift));
   }

Value 123456789 Shift 3 -> 789123456
Value 123456789 Shift -3 -> 456789123
Value 123456789 Shift 1 -> 912345678
Value 123456789 Shift -1 -> 234567891
Value 123456789 Shift 11 -> 891234567
Value 123456789 Shift -11 -> 345678912
Value 123456789 Shift 18 -> 123456789
Value 12345678 Shift 3 -> 67812345
Value 12345678 Shift -3 -> 45678123
Value 12345678 Shift 1 -> 81234567
Value 12345678 Shift -1 -> 23456781
Value 12345678 Shift 11 -> 67812345
Value 12345678 Shift -11 -> 45678123
Value 12345678 Shift 18 -> 78123456

【讨论】:

  • 哇,太酷了!我只是想找到一个解决方案,当班次为负时,如何处理比数字长度更大的班次,但是您的解决方案可以很好地处理这种情况,并且不会产生没有的 0 :)
  • @Me.Name 看起来令人印象深刻,不幸的是它不适用于uint.MaxValue;你应该计算并返回一个long 值类型以避免溢出问题。
  • @Dzienny 感谢您的评论。 uint.MaxValue 对于大多数班次确实会失败,因为结果不适合 uint,但是 OP 表示输入会更小,并且返回值基于原始方法签名。不过,对于那些想要一个没有警告的函数的人来说,这是一个有效的观点:将所有 uint 更改为 ulong,包括返回值(但不更改输入值),确实可以解决问题。
  • @DarkSide 很高兴您可以使用它 :) 大于长度的负移位的秘诀是在将移位更改为(长度移位)之前对长度进行模数
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多