How to Wrap Around a Range

How can I wrap with a range of numbers?

You can do this as well :

var limit= 100;
var str= "";

for (var i = 1; i <= limit; ++i) {
str += i + ((i % 10) ? " " : "\n");
}
console.log(str);

How to wrap around a range

What you are looking for is the modulus. The fmod function will not work because it calculates the remainder and not the arithmetic modulus. Something like this should work:

inline double wrapAngle( double angle )
{
double twoPi = 2.0 * 3.141592865358979;
return angle - twoPi * floor( angle / twoPi );
}

Edit:

The remainder is commonly defined as what is left over after long division (eg. the remainder of 18/4 is 2, because 18 = 4 * 4 + 2). This gets hairy when you have negative numbers. The common way to find the remainder of a signed division is for the remainder to have the same sign as the result (eg. the remainder of -18/4 is -2, because -18 = -4 * 4 + -2).

The definition of x modulus y is the smallest positive value of m in the equation x=y*c+m, given c is an integer. So 18 mod 4 would be 2 (where c=4), however -18 mod 4 would also be 2 (where c=-5).

The simplest calculation of x mod y is x-y*floor(x/y), where floor is the largest integer that is less than or equal to the input.

Wrap value into range [min,max] without division

You can wrap it using two modulo operations, which is still equivalent to a division. I don't think there is a more efficient way of doing this without assuming something about x.

x = (((x - x_min) % (x_max - x_min)) + (x_max - x_min)) % (x_max - x_min) + x_min;

The additional sum and modulo in the formula are to handle those cases where x is actually less than x_min and the modulo might come up negative. Or you could do this with an if, and a single modular division:

if (x < x_min)
x = x_max - (x_min - x) % (x_max - x_min);
else
x = x_min + (x - x_min) % (x_max - x_min);

Unless x is not far from x_min and x_max, and is reachable with very few sums or subtractions (think also error propagation), I think the modulo is your only available method.

Without division

Keeping in mind that error propagation might become relevant, we can do this with a cycle:

d = x_max - x_min;
if (abs(d) < MINIMUM_PRECISION) {
return x_min; // Actually a divide by zero error :-)
}
while (x < x_min) {
x += d;
}
while (x > x_max) {
x -= d;
}

Note on probabilities

The use of modular arithmetic has some statistical implications (floating point arithmetic also would have different ones).

For example say we wrap a random value between 0 and 5 included (e.g. a six-sided dice result) into a [0,1] range (i.e. a coin flip). Then

0 -> 0      1 -> 1
2 -> 0 3 -> 1
4 -> 0 5 -> 1

if the input has flat spectrum, i.e., every number (0-5) has 1/6 probability, the output will also be flat, and each item will have 3/6 = 50% probability.

But if we had a five-sided dice (0-4), or if we had a random number between 0 and 32767 and wanted to reduce it in the (0, 99) range to get a percentage, the output would not be flat, and some number would be slightly (or not so slightly) more likely than others. In the five-sided dice to coin-flip case, heads vs. tails would be 60%-40%. In the 32767-to-percent case, percentages below 67 would be CEIL(32767/100)/FLOOR(32767/100) = 0.3% more likely to come up than the others.

(To see this more clearly, consider the number to be from "00000" to "32767": once every 328 throws, the first three digits of the number will be "327". When this happens, the last two digits can only go from "00" to "67", they cannot be "68" to "99" because 32768 is out of range. So, digits from 00 to 67 are slightly more likely.

So, if one wanted a flat output, one would have to ensure that (max-min) was a divisor of the input range. In the case of 32767 and 100, the input range would have to be truncated at the nearest hundred (minus one), 32699, so that (0-32699) contained 32700 outcomes. Whenever the input was >= 32700, the input function would have to be called again to obtain a new value:

function reduced() {
#ifdef RECURSIVE
int x = get_random();
if (x > MAX_ALLOWED) {
return reduced(); // Retry
}
#else
for (;;) {
int x = get_random();
int d = x_max - x_min;
if (x > MAX_ALLOWED) {
continue; // Retry
}
}
#endif
return x_min + (
(
(x - x_min) % d
) + d
) % d;

When (INPUTRANGE%OUTPUTRANGE)/(INPUTRANGE) is significant, the overhead might be considerable (e.g. reducing 0-197 to 0-99 requires making roughly twice as many calls).

If the input range is less than the output range (e.g. we have a coin flipper and we want to make a dice tosser), multiply (do not add) using Horner's algorithm as many times as required to get an input range which is larger. Coin flip has a range of 2, CEIL(LN(OUTPUTRANGE)/LN(INPUTRANGE)) is 3, so we need three multiplications:

for (;;) {
x = ( flip() * 2 + flip() ) * 2 + flip();
if (x < 6) {
break;
}
}

or to get a number between 122 and 221 (range=100) out of a dice tosser:

for (;;) {
// ROUNDS = 1 + FLOOR(LN(OUTPUTRANGE)/LN(INPUTRANGE)) and can be hardwired
// INPUTRANGE is 6
// x = 0; for (i = 0; i < ROUNDS; i++) { x = 6*x + dice(); }
x = dice() + 6 * (
dice() + 6 * (
dice() /* + 6*... */
)
);
if (x < 200) {
break;
}
}
// x is now 0..199, x/2 is 0..99
y = 122 + x/2;

Wrap unsigned integer addition/subtraction around a range

If you are willing to change dx from const int to int, you can do the arithmetic in a loop. This avoids possible problems with upper - lower exceeding INT_MAX.

#include <stdio.h>

unsigned int wrap_add(unsigned int val,
int dx,
const unsigned int lower,
const unsigned int upper);

int main(void)
{
printf("Range [0, 10]: 5 + (-6) = %u\n", wrap_add(5, -6, 0, 10));
printf("Range [1, 3]: 2 + 3 = %u\n", wrap_add(2, 3, 1, 3));
printf("Range [2, 5]: 2 + (-9) = %u\n", wrap_add(2, -9, 2, 5));

return 0;
}

unsigned int wrap_add(unsigned int val,
int dx,
const unsigned int lower,
const unsigned int upper)
{
while (dx < 0) {
if (val == lower) {
val = upper;
} else {
--val;
}
++dx;
}

while (dx > 0) {
if (val == upper) {
val = lower;
} else {
++val;
}
--dx;
}

return val;
}

Program output:

Range [0, 10]: 5 + (-6) = 10
Range [1, 3]: 2 + 3 = 2
Range [2, 5]: 2 + (-9) = 5

Wrapping a float between a number system without IF statements in c++?

Let assume we got wrap open range (a0,a1) where a0<0 and a1>0 and input number is x I would start experimenting with

x' = ((x/a0) - floor(x/a0))*a0 // negative x
x' = ((x/a1) - floor(x/a1))*a1 // positive x

Now the only problem how to decide which one to use without branching (if statements). I would use binary bit manipulation integer representation of float value. The sign bit is the MSB and float is 32 bit. So first obtain sign value of float and then convert it to 0 or 1:

unsigned int *px=(unsigned int*)&x;
float a=(unsigned int)(px[0]>>31);

Beware that unsigned int must be the same bit-width or less (but then use correct bit-shift of coarse) than float I usually use DWORD for such thing but not all compilers know such a type (it should be defined also in windows.h btw). Now just use it to select between the two equations. When I put all together in C++:

float wrap(float x,float a0,float a1)
{
float a;
a=x/a0; a0*=(a-floor(a)); // x<=0
a=x/a1; a1*=(a-floor(a)); // x>=0
unsigned int *px=(unsigned int*)&x; // px is integer representaion of x
a=(unsigned int)(px[0]>>31); // a = 0 for x>=0 and a = 1 for x<=0
// now just combine
a0*=( a);
a1*=(1.0-a);
return a0+a1;
}

Here result for range (-3,+3)

   x   |    x'
---------------
-6.25 | -0.25
-6.00 | 0.00
-5.75 | -2.75
-5.50 | -2.50
-5.25 | -2.25
-5.00 | -2.00
-4.75 | -1.75
-4.50 | -1.50
-4.25 | -1.25
-4.00 | -1.00
-3.75 | -0.75
-3.50 | -0.50
-3.25 | -0.25
-3.00 | 0.00
-2.75 | -2.75
-2.50 | -2.50
-2.25 | -2.25
-2.00 | -2.00
-1.75 | -1.75
-1.50 | -1.50
-1.25 | -1.25
-1.00 | -1.00
-0.75 | -0.75
-0.50 | -0.50
-0.25 | -0.25
---------------
0.00 | 0.00
---------------
0.25 | 0.25
0.50 | 0.50
0.75 | 0.75
1.00 | 1.00
1.25 | 1.25
1.50 | 1.50
1.75 | 1.75
2.00 | 2.00
2.25 | 2.25
2.50 | 2.50
2.75 | 2.75
3.00 | 0.00
3.25 | 0.25
3.50 | 0.50
3.75 | 0.75
4.00 | 1.00
4.25 | 1.25
4.50 | 1.50
4.75 | 1.75
5.00 | 2.00
5.25 | 2.25
5.50 | 2.50
5.75 | 2.75
6.00 | 0.00
6.25 | 0.25

Clean, efficient algorithm for wrapping integers in C++

The sign of a % b is only defined if a and b are both non-negative.

int Wrap(int kX, int const kLowerBound, int const kUpperBound)
{
int range_size = kUpperBound - kLowerBound + 1;

if (kX < kLowerBound)
kX += range_size * ((kLowerBound - kX) / range_size + 1);

return kLowerBound + (kX - kLowerBound) % range_size;
}

Wrap around range of unsigned int in C++?

When an out-of-range value is converted to an unsigned type, the result is the remainder of it modulo the number of values the target unsigned type can hold. For instance, the result of n converted to unsigned char is n % 256, because unsigned char can hold values 0 to 255.

It's similar in your example, the wrap-around is done using 4294967296, the number of values that a 32-bit unsigned integer can hold.



Related Topics



Leave a reply



Submit