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.










share|improve this question
























  • "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















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.










share|improve this question
























  • "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













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.










share|improve this question















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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


















  • "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












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:



enter image description here



It is useful to first shift the minimum to zero:



enter image description here



This function form can be computed as a sum of the two shifted absolute value functions below:



enter image description here



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).






share|improve this answer



















  • 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











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















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

























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:



enter image description here



It is useful to first shift the minimum to zero:



enter image description here



This function form can be computed as a sum of the two shifted absolute value functions below:



enter image description here



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).






share|improve this answer



















  • 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















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:



enter image description here



It is useful to first shift the minimum to zero:



enter image description here



This function form can be computed as a sum of the two shifted absolute value functions below:



enter image description here



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).






share|improve this answer



















  • 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













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:



enter image description here



It is useful to first shift the minimum to zero:



enter image description here



This function form can be computed as a sum of the two shifted absolute value functions below:



enter image description here



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).






share|improve this answer














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:



enter image description here



It is useful to first shift the minimum to zero:



enter image description here



This function form can be computed as a sum of the two shifted absolute value functions below:



enter image description here



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).







share|improve this answer














share|improve this answer



share|improve this answer








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














  • 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


















 

draft saved


draft discarded



















































 


draft saved


draft discarded














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





















































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







這個網誌中的熱門文章

Tangent Lines Diagram Along Smooth Curve

Yusuf al-Mu'taman ibn Hud

Zucchini