C++ 在不使用除法/模的情况下,将随机整数剪裁为一个值范围

C++ 在不使用除法/模的情况下,将随机整数剪裁为一个值范围,c++,C++,可以这样做: int clamp(int rnd, int min, int max) { return min + rnd % (max - min + 1); } 这可以不用除法吗? 返回值不一定要匹配,但是,必须保持均匀分布 rnd、min和max是任意整数rnd在我的例子中是一个随机整数 一种可能的解决方案是在[0…1)先使用,然后乘法,但我想知道是否有一个更简单的解决方案不涉及浮点和/或除法。如果根据注释,您有一个32位int和rnd输入,均匀分布在-2^31和2^31之间,

可以这样做:

int clamp(int rnd, int min, int max)
{
    return min + rnd % (max - min + 1);
}
这可以不用除法吗? 返回值不一定要匹配,但是,必须保持均匀分布

rnd
min
max
是任意整数
rnd
在我的例子中是一个随机整数


一种可能的解决方案是在
[0…1)
先使用,然后乘法,但我想知道是否有一个更简单的解决方案不涉及浮点和/或除法。

如果根据注释,您有一个32位int和rnd输入,均匀分布在-2^31和2^31之间,您可以将输出计算为
min+(((长-长)max-(长)min)*(无符号长)rnd))>>32
有效地将rnd缩放到0..1,将值缩放到最小..max。因为您编写的代码不关心标准,所以我并不特别关注有符号/无符号转换实践和警告。只是给出了一个总体思路-先乘然后移位,而不是除法

int clamp(uint32_t rnd, int min, int max)
{
    return min + (1ull*rnd*(max - min + 1)) >> 32;
}

如果根据注释,您的32位int和rnd输入均匀分布在-2^31和2^31之间,您可以将输出计算为
min+(((长-长)max-(长)min)*(无符号长)rnd))>>32
有效地将rnd缩放到0..1,将值缩放到最小..max。因为您编写的代码不关心标准,所以我并不特别关注有符号/无符号转换实践和警告。只是给出了一个总体思路-先乘然后移位,而不是除法

int clamp(uint32_t rnd, int min, int max)
{
    return min + (1ull*rnd*(max - min + 1)) >> 32;
}

你是否试图用给定的最小值和最大值得到一个统一的整数分布?如果是,那么看看你是否能确保(max-min+1)是2的完美幂,然后你可以使用
返回min+rnd&(max-min)
因为
n%pow(2,k)=n&(pow(2,k)-1)
@LakshayGarg我更新了这个问题。
min
max
是任意的,我指定必须保持一致性,例如我不能简单地选择一些位的范围。rnd的范围呢?如果这个是2的幂(比如说它是int的全范围),您可以使用shift代替divisionWell,int是16位有符号的,而不是32,但是如果您的int是长的,您可以使用(long-long)cast代替long,按32移位并按如下比例缩放min+(((long)max-(long)min)*(long)rnd)>>16有效地将rnd缩放到0..1,将值缩放到min..max您是否尝试使用给定的最小值和最大值来实现统一的int分布?如果是,请查看是否可以确保(max-min+1)是2的完美幂,然后您可以使用
返回最小值+rnd&(max-min)
因为
n%pow(2,k)=n&(pow(2,k)-1)
@LakshayGarg我更新了这个问题。
min
max
是任意的,我指定必须保持一致性,例如我不能简单地选择一些位的范围。rnd的范围呢?如果这个是2的幂(比如说它是int的全范围),您可以使用shift代替divisionWell,int是16位有符号的,而不是32,但是如果您的int是长的,您可以使用(long-long)cast代替long,按32移位并按如下方式缩放min+((long)max-(long)min)*(long)rnd)>>16,它有效地将rnd缩放为0..1,并将值缩放为min..max