使用 C# 循环移位 Int32 位
Circular shift Int32 digits using C#
成员,
我想做的是右移或左移 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是一个非负数
- 正旋转整数应向右移动,负旋转向左移动。
我的算法已经完成了所有这些,我想知道是否有办法稍微调整一下,是否有更好的算法解决问题?
因为我无法抗拒 'has to have an arithmetic approach' 挑战 :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
成员,
我想做的是右移或左移 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是一个非负数
- 正旋转整数应向右移动,负旋转向左移动。
我的算法已经完成了所有这些,我想知道是否有办法稍微调整一下,是否有更好的算法解决问题?
因为我无法抗拒 'has to have an arithmetic approach' 挑战 :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