Limit a value between min and max using only arithmetic
up vote
2
down vote
favorite
Is it possible to limit a value in a given range, between min and max, using only arithmetic? That is, +
-
x
/
and %
?
I am not able to use functions such as min
, max
nor IF
-statements.
Let's assume I have a range of [1850, 1880]
, for any values < 1850
, it should display 1850
. For values > 1880
, 1880
should be displayed. It would also be acceptable if only 1850
was displayed outside the range.
I tried:
x = (((x - xmax) % (xmax - xmin)) + (xmax - xmin)) % (xmax - xmin) + xmin
but it gives different values in the middle of the range for values lower than xmin
.
math max min plc clamp
add a comment |
up vote
2
down vote
favorite
Is it possible to limit a value in a given range, between min and max, using only arithmetic? That is, +
-
x
/
and %
?
I am not able to use functions such as min
, max
nor IF
-statements.
Let's assume I have a range of [1850, 1880]
, for any values < 1850
, it should display 1850
. For values > 1880
, 1880
should be displayed. It would also be acceptable if only 1850
was displayed outside the range.
I tried:
x = (((x - xmax) % (xmax - xmin)) + (xmax - xmin)) % (xmax - xmin) + xmin
but it gives different values in the middle of the range for values lower than xmin
.
math max min plc clamp
"number" is ambiguous in computer science. What type of number are you talking about? Signed integer? Fixed-length unsigned? Double? Please clarify. Also -- if you have a programming language in mind, please stipulate. The operators/
and%
have different semantics in different programming languages.
– John Coleman
Nov 7 at 11:31
@JohnColeman It's the IEC 61131-3 languages and the data type is ANY_INT. To keep it simple let's just say that my question was about a signed integer. By "/" I mean division and by "%" I mean the modulo operation, which in my case is actually "MOD"
– Qliver
Nov 7 at 11:47
1
So by "division" you mean "integer (truncating) division"? Also -- how does%
work with negative values (since you are talking about signed integers)? This is one area where there is a surprising amount of variation between various programming languages
– John Coleman
Nov 7 at 11:56
1
@JohnColeman That's right, integer truncating division. As for%
, in my case the result has the same sign as the dividend.
– Qliver
Nov 7 at 12:19
add a comment |
up vote
2
down vote
favorite
up vote
2
down vote
favorite
Is it possible to limit a value in a given range, between min and max, using only arithmetic? That is, +
-
x
/
and %
?
I am not able to use functions such as min
, max
nor IF
-statements.
Let's assume I have a range of [1850, 1880]
, for any values < 1850
, it should display 1850
. For values > 1880
, 1880
should be displayed. It would also be acceptable if only 1850
was displayed outside the range.
I tried:
x = (((x - xmax) % (xmax - xmin)) + (xmax - xmin)) % (xmax - xmin) + xmin
but it gives different values in the middle of the range for values lower than xmin
.
math max min plc clamp
Is it possible to limit a value in a given range, between min and max, using only arithmetic? That is, +
-
x
/
and %
?
I am not able to use functions such as min
, max
nor IF
-statements.
Let's assume I have a range of [1850, 1880]
, for any values < 1850
, it should display 1850
. For values > 1880
, 1880
should be displayed. It would also be acceptable if only 1850
was displayed outside the range.
I tried:
x = (((x - xmax) % (xmax - xmin)) + (xmax - xmin)) % (xmax - xmin) + xmin
but it gives different values in the middle of the range for values lower than xmin
.
math max min plc clamp
math max min plc clamp
edited Nov 7 at 11:51
John Coleman
33.6k53269
33.6k53269
asked Nov 7 at 9:20
Qliver
144
144
"number" is ambiguous in computer science. What type of number are you talking about? Signed integer? Fixed-length unsigned? Double? Please clarify. Also -- if you have a programming language in mind, please stipulate. The operators/
and%
have different semantics in different programming languages.
– John Coleman
Nov 7 at 11:31
@JohnColeman It's the IEC 61131-3 languages and the data type is ANY_INT. To keep it simple let's just say that my question was about a signed integer. By "/" I mean division and by "%" I mean the modulo operation, which in my case is actually "MOD"
– Qliver
Nov 7 at 11:47
1
So by "division" you mean "integer (truncating) division"? Also -- how does%
work with negative values (since you are talking about signed integers)? This is one area where there is a surprising amount of variation between various programming languages
– John Coleman
Nov 7 at 11:56
1
@JohnColeman That's right, integer truncating division. As for%
, in my case the result has the same sign as the dividend.
– Qliver
Nov 7 at 12:19
add a comment |
"number" is ambiguous in computer science. What type of number are you talking about? Signed integer? Fixed-length unsigned? Double? Please clarify. Also -- if you have a programming language in mind, please stipulate. The operators/
and%
have different semantics in different programming languages.
– John Coleman
Nov 7 at 11:31
@JohnColeman It's the IEC 61131-3 languages and the data type is ANY_INT. To keep it simple let's just say that my question was about a signed integer. By "/" I mean division and by "%" I mean the modulo operation, which in my case is actually "MOD"
– Qliver
Nov 7 at 11:47
1
So by "division" you mean "integer (truncating) division"? Also -- how does%
work with negative values (since you are talking about signed integers)? This is one area where there is a surprising amount of variation between various programming languages
– John Coleman
Nov 7 at 11:56
1
@JohnColeman That's right, integer truncating division. As for%
, in my case the result has the same sign as the dividend.
– Qliver
Nov 7 at 12:19
"number" is ambiguous in computer science. What type of number are you talking about? Signed integer? Fixed-length unsigned? Double? Please clarify. Also -- if you have a programming language in mind, please stipulate. The operators
/
and %
have different semantics in different programming languages.– John Coleman
Nov 7 at 11:31
"number" is ambiguous in computer science. What type of number are you talking about? Signed integer? Fixed-length unsigned? Double? Please clarify. Also -- if you have a programming language in mind, please stipulate. The operators
/
and %
have different semantics in different programming languages.– John Coleman
Nov 7 at 11:31
@JohnColeman It's the IEC 61131-3 languages and the data type is ANY_INT. To keep it simple let's just say that my question was about a signed integer. By "/" I mean division and by "%" I mean the modulo operation, which in my case is actually "MOD"
– Qliver
Nov 7 at 11:47
@JohnColeman It's the IEC 61131-3 languages and the data type is ANY_INT. To keep it simple let's just say that my question was about a signed integer. By "/" I mean division and by "%" I mean the modulo operation, which in my case is actually "MOD"
– Qliver
Nov 7 at 11:47
1
1
So by "division" you mean "integer (truncating) division"? Also -- how does
%
work with negative values (since you are talking about signed integers)? This is one area where there is a surprising amount of variation between various programming languages– John Coleman
Nov 7 at 11:56
So by "division" you mean "integer (truncating) division"? Also -- how does
%
work with negative values (since you are talking about signed integers)? This is one area where there is a surprising amount of variation between various programming languages– John Coleman
Nov 7 at 11:56
1
1
@JohnColeman That's right, integer truncating division. As for
%
, in my case the result has the same sign as the dividend.– Qliver
Nov 7 at 12:19
@JohnColeman That's right, integer truncating division. As for
%
, in my case the result has the same sign as the dividend.– Qliver
Nov 7 at 12:19
add a comment |
1 Answer
1
active
oldest
votes
up vote
3
down vote
If you know the size of the integer type, you can extract its sign bit (assuming two's complement) using integer division:
// 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);
}
This returns 1 if s < 0
and 0 otherwise; it can be used to calculate the absolute value:
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;
}
The desired function looks like this:
It is useful to first shift the minimum to zero:
This function form can be computed as a sum of the two shifted absolute value functions below:
However the resultant function is scaled by a factor of 2; shifting to zero helps here because we only need to divide by 2, and shift back to the original minimum:
// 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;
}
This solution, although satisfies the requirements of the problem, is limited to signed integer types (and languages which allow integer overflow - I'm unsure of how this could be overcome in e.g. Java).
1
This is impressive (+1) although given the ambiguity in the original question, it is impossible to tell if it satisfies whatever unstated constraints they have on the solution.
– John Coleman
Nov 7 at 11:35
@JohnColeman Indeed, I'm aware of the rather restrictive assumptions made by this solution. I'll try to think of a more general one in the meantime.
– meowgoesthedog
Nov 7 at 11:41
I suspect that without a lot of constraints a solution is impossible.
– John Coleman
Nov 7 at 11:48
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
3
down vote
If you know the size of the integer type, you can extract its sign bit (assuming two's complement) using integer division:
// 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);
}
This returns 1 if s < 0
and 0 otherwise; it can be used to calculate the absolute value:
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;
}
The desired function looks like this:
It is useful to first shift the minimum to zero:
This function form can be computed as a sum of the two shifted absolute value functions below:
However the resultant function is scaled by a factor of 2; shifting to zero helps here because we only need to divide by 2, and shift back to the original minimum:
// 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;
}
This solution, although satisfies the requirements of the problem, is limited to signed integer types (and languages which allow integer overflow - I'm unsure of how this could be overcome in e.g. Java).
1
This is impressive (+1) although given the ambiguity in the original question, it is impossible to tell if it satisfies whatever unstated constraints they have on the solution.
– John Coleman
Nov 7 at 11:35
@JohnColeman Indeed, I'm aware of the rather restrictive assumptions made by this solution. I'll try to think of a more general one in the meantime.
– meowgoesthedog
Nov 7 at 11:41
I suspect that without a lot of constraints a solution is impossible.
– John Coleman
Nov 7 at 11:48
add a comment |
up vote
3
down vote
If you know the size of the integer type, you can extract its sign bit (assuming two's complement) using integer division:
// 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);
}
This returns 1 if s < 0
and 0 otherwise; it can be used to calculate the absolute value:
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;
}
The desired function looks like this:
It is useful to first shift the minimum to zero:
This function form can be computed as a sum of the two shifted absolute value functions below:
However the resultant function is scaled by a factor of 2; shifting to zero helps here because we only need to divide by 2, and shift back to the original minimum:
// 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;
}
This solution, although satisfies the requirements of the problem, is limited to signed integer types (and languages which allow integer overflow - I'm unsure of how this could be overcome in e.g. Java).
1
This is impressive (+1) although given the ambiguity in the original question, it is impossible to tell if it satisfies whatever unstated constraints they have on the solution.
– John Coleman
Nov 7 at 11:35
@JohnColeman Indeed, I'm aware of the rather restrictive assumptions made by this solution. I'll try to think of a more general one in the meantime.
– meowgoesthedog
Nov 7 at 11:41
I suspect that without a lot of constraints a solution is impossible.
– John Coleman
Nov 7 at 11:48
add a comment |
up vote
3
down vote
up vote
3
down vote
If you know the size of the integer type, you can extract its sign bit (assuming two's complement) using integer division:
// 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);
}
This returns 1 if s < 0
and 0 otherwise; it can be used to calculate the absolute value:
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;
}
The desired function looks like this:
It is useful to first shift the minimum to zero:
This function form can be computed as a sum of the two shifted absolute value functions below:
However the resultant function is scaled by a factor of 2; shifting to zero helps here because we only need to divide by 2, and shift back to the original minimum:
// 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;
}
This solution, although satisfies the requirements of the problem, is limited to signed integer types (and languages which allow integer overflow - I'm unsure of how this could be overcome in e.g. Java).
If you know the size of the integer type, you can extract its sign bit (assuming two's complement) using integer division:
// 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);
}
This returns 1 if s < 0
and 0 otherwise; it can be used to calculate the absolute value:
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;
}
The desired function looks like this:
It is useful to first shift the minimum to zero:
This function form can be computed as a sum of the two shifted absolute value functions below:
However the resultant function is scaled by a factor of 2; shifting to zero helps here because we only need to divide by 2, and shift back to the original minimum:
// 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;
}
This solution, although satisfies the requirements of the problem, is limited to signed integer types (and languages which allow integer overflow - I'm unsure of how this could be overcome in e.g. Java).
edited Nov 7 at 19:05
answered Nov 7 at 10:40
meowgoesthedog
8,4733823
8,4733823
1
This is impressive (+1) although given the ambiguity in the original question, it is impossible to tell if it satisfies whatever unstated constraints they have on the solution.
– John Coleman
Nov 7 at 11:35
@JohnColeman Indeed, I'm aware of the rather restrictive assumptions made by this solution. I'll try to think of a more general one in the meantime.
– meowgoesthedog
Nov 7 at 11:41
I suspect that without a lot of constraints a solution is impossible.
– John Coleman
Nov 7 at 11:48
add a comment |
1
This is impressive (+1) although given the ambiguity in the original question, it is impossible to tell if it satisfies whatever unstated constraints they have on the solution.
– John Coleman
Nov 7 at 11:35
@JohnColeman Indeed, I'm aware of the rather restrictive assumptions made by this solution. I'll try to think of a more general one in the meantime.
– meowgoesthedog
Nov 7 at 11:41
I suspect that without a lot of constraints a solution is impossible.
– John Coleman
Nov 7 at 11:48
1
1
This is impressive (+1) although given the ambiguity in the original question, it is impossible to tell if it satisfies whatever unstated constraints they have on the solution.
– John Coleman
Nov 7 at 11:35
This is impressive (+1) although given the ambiguity in the original question, it is impossible to tell if it satisfies whatever unstated constraints they have on the solution.
– John Coleman
Nov 7 at 11:35
@JohnColeman Indeed, I'm aware of the rather restrictive assumptions made by this solution. I'll try to think of a more general one in the meantime.
– meowgoesthedog
Nov 7 at 11:41
@JohnColeman Indeed, I'm aware of the rather restrictive assumptions made by this solution. I'll try to think of a more general one in the meantime.
– meowgoesthedog
Nov 7 at 11:41
I suspect that without a lot of constraints a solution is impossible.
– John Coleman
Nov 7 at 11:48
I suspect that without a lot of constraints a solution is impossible.
– John Coleman
Nov 7 at 11:48
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53186524%2flimit-a-value-between-min-and-max-using-only-arithmetic%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
"number" is ambiguous in computer science. What type of number are you talking about? Signed integer? Fixed-length unsigned? Double? Please clarify. Also -- if you have a programming language in mind, please stipulate. The operators
/
and%
have different semantics in different programming languages.– John Coleman
Nov 7 at 11:31
@JohnColeman It's the IEC 61131-3 languages and the data type is ANY_INT. To keep it simple let's just say that my question was about a signed integer. By "/" I mean division and by "%" I mean the modulo operation, which in my case is actually "MOD"
– Qliver
Nov 7 at 11:47
1
So by "division" you mean "integer (truncating) division"? Also -- how does
%
work with negative values (since you are talking about signed integers)? This is one area where there is a surprising amount of variation between various programming languages– John Coleman
Nov 7 at 11:56
1
@JohnColeman That's right, integer truncating division. As for
%
, in my case the result has the same sign as the dividend.– Qliver
Nov 7 at 12:19