2

是否可以仅使用算术将值限制在给定范围内,介于最小值和最大值之间?也就是说,+ - x /%

我无法使用min,maxIF- 语句等功能。

假设我有一个范围[1850, 1880],对于任何值< 1850,它都应该显示1850。对于 values > 18801880应显示。如果仅1850显示在范围之外也是可以接受的。

我试过了:

x = (((x - xmax) % (xmax - xmin)) + (xmax - xmin)) % (xmax - xmin) + xmin 

但对于低于xmin.

4

3 回答 3

5

如果您知道整数类型的大小,则可以使用整数除法提取其符号位(假设为二进制补码):

// Example in C
int sign_bit(int s) 
{
    // cast to unsigned (important)
    unsigned u = (unsigned)s;

    // number of bits in int
    // if your integer size is fixed, this is just a constant
    static const unsigned b = sizeof(int) * 8;

    // pow(2, b - 1)
    // again, a constant which can be pre-computed
    static const unsigned p = 1 << (b - 1);

    // use integer division to get top bit
    return (int)(u / p);
}

如果返回 1 s < 0,否则返回 0;它可以用来计算绝对值

int abs_arith(int v)
{
    // sign bit
    int b = sign_bit(v);

    // actual sign (+1 / -1)
    int s = 1 - 2 * b;

    // sign(v) * v = abs(v)
    return s * v;
}

所需的功能如下所示:

在此处输入图像描述

首先将最小值移为零很有用:

在此处输入图像描述

该函数形式可以计算为以下两个移位绝对值函数的总和:

在此处输入图像描述

然而,结果函数被缩放了 2 倍;移到零在这里有帮助,因为我们只需要除以 2,然后移回原来的最小值:

// Example in C
int clamp_minmax(int val, int min, int max)
{
    // range length
    int range = max - min;

    // shift minimum to zero
    val = val - min;

    // blue function
    int blue = abs_arith(val);

    // green function
    int green = range - abs_arith(val - range);

    // add and divide by 2
    val = (blue + green) / 2;        

    // shift to original minimum
    return val + min;
}

这个解决方案虽然满足了问题的要求,但仅限于有符号整数类型(以及允许整数溢出的语言——我不确定如何在例如 Java 中克服这一点)。

于 2018-11-07T10:40:57.887 回答
2

我在乱搞... excel时发现了这个。它仅适用于严格的正整数。虽然这不像 meowgoesthedog 的答案那样具有更多限制性,因为他还通过在最后除以 2 有效地将整数空间减半。它不使用模组。

//A = 1 if x <= min
//A = 0 if x >= min
A = 1-(min-min/x)/min 

//B = 0 if x <= max
//B = 1 if x > max
B = (max-max/x)/max

x = A*min + (1-A)*(1-B)*x + B*max
于 2018-11-26T23:28:08.850 回答
-2

我在 Python 中找到了这个解决方案:

A = -1  # Minimum value
B = +1  # Maximum value
x = min(max(x, A), B)
于 2020-07-14T09:16:19.763 回答