Most Efficient/Elegant Way to Clip a Number

Most efficient/elegant way to clip a number?

What about boring, old, readable, and shortest yet:

float clip(float n, float lower, float upper) {
return std::max(lower, std::min(n, upper));
}

?

This expression could also be 'genericized' like so:

template <typename T>
T clip(const T& n, const T& lower, const T& upper) {
return std::max(lower, std::min(n, upper));
}

Update

Billy ONeal added:

Note that on windows you might have to define NOMINMAX because they define min and max macros which conflict

Most efficient way to clip a value to repeat through a range?

it is like this:

min = VALUE;
max = VALUE;
x = (((x - min) + 1) % (max - min)) + min

here x will be inside min and max - 1 when you repeat the last line of code

EDIT:

and to match your exact table:

output = (input - min) % (max - min) + min;

EDIT 2:

if modulus is not defined for negative numbers:

if (input >= min)
output = (input - min) % (max - min) + min;
else
output = max - ((max - input) % (max - min));

What's the most elegant way to cap a number to a segment?

The way you do it is pretty standard. You can define a utility clamp function:

/**
* Returns a number whose value is limited to the given range.
*
* Example: limit the output of this computation to between 0 and 255
* (x * 255).clamp(0, 255)
*
* @param {Number} min The lower boundary of the output range
* @param {Number} max The upper boundary of the output range
* @returns A number in the range [min, max]
* @type Number
*/
Number.prototype.clamp = function(min, max) {
return Math.min(Math.max(this, min), max);
};

(Although extending language built-ins is generally frowned upon)

Fastest way to clamp a real (fixed/floating point) value?

For the 16.16 representation, the simple ternary is unlikely to be bettered speed-wise.

And for doubles, because you need it standard/portable C, bit-fiddling of any kind will end badly.

Even if a bit-fiddle was possible (which I doubt), you'd be relying on the binary representation of doubles. THIS (and their size) IS IMPLEMENTATION-DEPENDENT.

Possibly you could "guess" this using sizeof(double) and then comparing the layout of various double values against their common binary representations, but I think you're on a hiding to nothing.

The best rule is TELL THE COMPILER WHAT YOU WANT (ie ternary), and let it optimise for you.

EDIT: Humble pie time. I just tested quinmars idea (below), and it works - if you have IEEE-754 floats. This gave a speedup of about 20% on the code below. IObviously non-portable, but I think there may be a standardised way of asking your compiler if it uses IEEE754 float formats with a #IF...?

  double FMIN = 3.13;
double FMAX = 300.44;

double FVAL[10] = {-100, 0.23, 1.24, 3.00, 3.5, 30.5, 50 ,100.22 ,200.22, 30000};
uint64 Lfmin = *(uint64 *)&FMIN;
uint64 Lfmax = *(uint64 *)&FMAX;

DWORD start = GetTickCount();

for (int j=0; j<10000000; ++j)
{
uint64 * pfvalue = (uint64 *)&FVAL[0];
for (int i=0; i<10; ++i)
*pfvalue++ = (*pfvalue < Lfmin) ? Lfmin : (*pfvalue > Lfmax) ? Lfmax : *pfvalue;
}

volatile DWORD hacktime = GetTickCount() - start;

for (int j=0; j<10000000; ++j)
{
double * pfvalue = &FVAL[0];
for (int i=0; i<10; ++i)
*pfvalue++ = (*pfvalue < FMIN) ? FMIN : (*pfvalue > FMAX) ? FMAX : *pfvalue;
}

volatile DWORD normaltime = GetTickCount() - (start + hacktime);

Most elegant way to clip a line?

Well, I ended up doing it myself.

For those intereseted, I ended up solving it by turning the line into a rectangle (with getBounds), then using Rectangle.intersect(clipRect,lineRect,intersectLineRect) to create the intersection, then turning the intersection back into a line.

What is the most efficient (speed) way to get a digit from a larger number?

If int is 32 bits, then:

static const int table[] =
{ 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
return number / table[position-1] % 10;

is a reasonable implementation:

  • It does not invoke pow or use floating-point arithmetic.
  • It uses one table look-up, one division by a variable, and one remainder operation with a constant (which a compiler can optimize to a multiplication and some shifts and adds).

(Note that position is adjusted in the table lookup to be one-based to match the code in the question, but common practice would be to call the units position position 0 instead of position 1.)

If digits are to be extracted for multiple positions or the whole number, then other implementations should be considered.

Most efficient way to divide a number w/ several options

You could compute the amount of leftover/waste that would come from each piece and sort it to find the minimum. Something like this?

// sample data
const lengths = [20, 24, 40, 48];
const piecesNeeded = 8;
const pieceLength = 11.75;

// how many pieces of a given length can we get from each unit of material?
const piecesPerItem = (materialLength, pieceSize) => Math.floor(materialLength / pieceSize);

// compute stats for cutting pieces
// from a given denomination of material
const computeWaste = (materialLength, pieceSize) => {
// pieces per unit of material
const perItem = piecesPerItem(materialLength, pieceSize);

// if the piece size is greater than the material size, bail
if (perItem < 1) {
return null;
}

// how many units of material would we need?
const itemsNeeded = Math.ceil(piecesNeeded / perItem);

// how much would be left over from each?
const wastePerItem = materialLength % pieceSize;

// return what we've learned
return {
perItem,
itemsNeeded,
materialLength,
wastePerItem,
totalWaste: wastePerItem * itemsNeeded
};
}

// compute the waste for each material length
const leftovers = lengths.map(length => computeWaste(length, pieceLength));

// sort by least total waste
leftovers.sort(({totalWaste: a}, {totalWaste: b}) => a - b)

// the first entry has the least total waste
console.log(leftovers[0]);

// emit all the results for inspection
console.log(leftovers);

Efficient way to code a number within a range?

You could use a mapping between value and output:

outputs = [ A, B, C, D, E, F, F, F, F, F]
output = outputs[(int)((value - 1)/ 100)]


Related Topics



Leave a reply



Submit