You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

通用整数数字旋转函数优化:支持正负偏移、右旋转及溢出检查

通用整数数字旋转函数的实现问题

背景

我正尝试实现一个通用函数,可将给定整数的数字向左或向右旋转n位。目前仅完成了左旋转的实现代码:

public static T RotateDigitsLeft<T>(this T value, int count) where T : IBinaryInteger<T> {
    var absoluteValue = T.Abs(value: value);
    var countAsT = T.CreateTruncating(value: count);
    var digitCount = absoluteValue.LogarithmBase10();
    var factor = BinaryIntegerConstants<T>.Ten.Exponentiate(exponent: (digitCount - countAsT));
    var endDigits = (absoluteValue / factor);
    var startDigits = (absoluteValue - (endDigits * factor));

    return T.CopySign(sign: value, value: ((startDigits * BinaryIntegerConstants<T>.Ten.Exponentiate(exponent: countAsT)) + endDigits));
}

问题

  1. 能否修改该函数以支持count为负值的场景?
  2. 部分旋转操作会因T类型的大小限制产生无效值,是否有合适的泛型方式检查并抛出异常?
  3. 能否修改函数以支持右旋转?

注意:优先采用算术实现的方案。

示例

  • 54321 → 43215(左旋转1位/右旋转4位)
  • 54321 → 32154(左旋转2位/右旋转3位)
  • 1123456789 → 1234567891(左旋转1位)
  • 1123456789 → EXCEPTION(右旋转1位)

解决方案

1. 支持count为负值的场景

先对count做归一化处理:基于数字总位数,将超出位数的旋转次数简化(比如5位数左旋转6位等价于左旋转1位);若count为负,直接转换为对应的正向旋转次数(比如右旋转1位等价于左旋转总位数-1位)。

核心修改逻辑:

var digitCount = absoluteValue.LogarithmBase10();
int intDigitCount = int.CreateTruncating(digitCount);
// 简化旋转次数,负数转为正向等效值
count = count % intDigitCount;
if (count < 0) count += intDigitCount;
var countAsT = T.CreateTruncating(count);

2. 泛型溢出检查与异常抛出

利用IBinaryInteger<T>提供的TryMultiply、TryAdd、TryDivide等方法,在算术操作前判断是否会超出T的范围,若操作失败则抛出OverflowException。

以核心计算步骤为例:

// 计算10的幂时检查溢出
var tenPower = BinaryIntegerConstants<T>.Ten.Exponentiate(countAsT);
// 乘法操作检查溢出
if (!T.TryMultiply(startDigits, tenPower, out var multiplied))
{
    throw new OverflowException($"旋转后的值超出类型 {typeof(T)} 的范围");
}
// 加法操作检查溢出
if (!T.TryAdd(multiplied, endDigits, out var resultValue))
{
    throw new OverflowException($"旋转后的值超出类型 {typeof(T)} 的范围");
}

3. 支持右旋转

右旋转的算术实现逻辑:将最后k位移到数字最前方,步骤如下:

  1. 计算数字总位数digitCount
  2. 取最后k位:endDigits = absoluteValue % (10^k)
  3. 取剩余前半部分:startDigits = absoluteValue / (10^k)
  4. 结果为:endDigits * 10^(digitCount - k) + startDigits

可以直接复用归一化后的count逻辑,将右旋转转为负count的左旋转,或单独实现右旋转函数:

public static T RotateDigitsRight<T>(this T value, int count) where T : IBinaryInteger<T>
{
    return value.RotateDigits(-count);
}

完整整合实现

public static T RotateDigits<T>(this T value, int count) where T : IBinaryInteger<T>
{
    if (value == T.Zero) return value;

    var absoluteValue = T.Abs(value);
    var digitCount = absoluteValue.LogarithmBase10();
    int intDigitCount = int.CreateTruncating(digitCount);
    if (intDigitCount == 0) return value;

    // 归一化旋转次数
    count = count % intDigitCount;
    if (count < 0) count += intDigitCount;
    if (count == 0) return value;

    var countAsT = T.CreateTruncating(count);
    T resultValue;

    // 左旋转核心逻辑
    var leftFactor = BinaryIntegerConstants<T>.Ten.Exponentiate(digitCount - countAsT);
    if (!T.TryDivide(absoluteValue, leftFactor, out var endDigits))
    {
        throw new OverflowException($"操作超出类型 {typeof(T)} 的范围");
    }
    var startDigits = absoluteValue - endDigits * leftFactor;

    var tenPowerLeft = BinaryIntegerConstants<T>.Ten.Exponentiate(countAsT);
    if (!T.TryMultiply(startDigits, tenPowerLeft, out var multipliedLeft))
    {
        throw new OverflowException($"旋转后的值超出类型 {typeof(T)} 的范围");
    }
    if (!T.TryAdd(multipliedLeft, endDigits, out resultValue))
    {
        throw new OverflowException($"旋转后的值超出类型 {typeof(T)} 的范围");
    }

    return T.CopySign(resultValue, value);
}

// 单独的右旋转入口
public static T RotateDigitsRight<T>(this T value, int count) where T : IBinaryInteger<T>
{
    return value.RotateDigits(-count);
}

补充说明:

  • 需确保LogarithmBase10方法能正确计算数字位数,对0做特殊处理
  • 所有算术操作均通过TryXXX方法做溢出校验,保证类型安全性
  • 旋转次数归一化避免了无效计算,提升了函数效率

内容的提问来源于stack exchange,提问作者Kittoes0124

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 06:15:26