【问题标题】:How do you create a function to wrap numbers to a specified range?如何创建一个函数来将数字包装到指定范围?
【发布时间】:2021-12-01 22:20:49
【问题描述】:

我正在尝试创建一个函数以在数学上使数字下溢或将数字下溢到指定范围内。我想当数字都是正数时我能够让它工作(取出Math.Abs(用于正数负数))但是负值或负值的范围失败。我想用数学解决这个问题,但不知道我做错了什么!

这是我当前对失败函数的实现:

    /// <summary>
    /// Wraps a value within the specified range, overflowing or underflowing as necessary.
    /// </summary>
    /// <param name="value">The number to wrap.</param>
    /// <param name="minimumValue">The minimum value in the range.</param>
    /// <param name="length">The number of values in the range to wrap across.</param>
    /// <returns>The <paramref name="value"/> wrapped to the specified range.</returns>
    /// <exception cref="ArgumentException">Thrown if <paramref name="length"/> is <c>0</c>.</exception>
    public static int Wrap(this int value, int minimumValue, int length)
    {
        if (length == 0)
            throw new ArgumentException($"{nameof(length)} must not be 0 in order to produce a range to wrap across.");
        else
        {
            var absoluteModulus = System.Math.Abs((value - minimumValue) % length);
            
            return (value < 0 ? length - absoluteModulus : absoluteModulus) + minimumValue;
        }
    }

以下是当前实现的一些测试数据和结果:

value minimumValue length expected actual Comment
128 256 128 256 256 Pass
255 256 256 511 257 Modulo is underflowing backwards!
-3 1 2 1 3 Somehow underflowing out of range!
-4 0 2 0 2 Again, underflowing out of range!
63 128 384 447 193 128 - 63 == 65, 384 - 65 == 319, 319 + 128 == 447, not 193‼
300 100 200 100 100 This overflow works!

【问题讨论】:

  • 如果length小于0怎么办?你需要考虑这种情况吗?
  • 这是一个不错的选择,但不是必需的。

标签: c# math overflow modulo underflow


【解决方案1】:

您似乎知道% 是余数运算,而不是modulus(如模运算),但简单地获取模数的绝对值是不正确的。您应该使用here 的答案之一。例如:

private static int Mod(int k, int n) {
    int remainder = k % n;
    return (remainder < 0) ? remainder + n : remainder;
}

// ... in the else branch, you can directly do
return Mod(value - minimumValue, length) + minimumValue;

您还以不同的方式处理value &lt; 0。否定的value 没有什么特别之处。 这里的特殊之处是一个负余数,它是一个永远不会由模运算产生的值。如果您将 value &lt; 0 替换为检查 (value - minimumValue) % length 是否为负数,您的代码也会起作用。

【讨论】:

    猜你喜欢
    • 2012-09-04
    • 2021-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多