简体   繁体   中英

Compute integer bounds to include scaled floating point values

I am trying to compute integer array bounds that will include floating point limits divided by a scale. For example, if my origin is 0, my floating point maximum is 10 then my integer array bounds need to be 2. The obvious formula is to divide my bounds by the scale, giving the incorrect result of 1.

I need to divide the inclusive maximum values by the scale and add one if the division is an exact multiple.

I am running into a mismatch between the normal way to define and use integer array indexes and my desired way to use real value coordinates. I am trying to map inclusive real value coordinates into integer array indexes, using a scaling term.

(I am actually working with two dimensional maps, but the problem can be expressed more simply in one dimension.)

This is wrong:

    int get_array_size(double, scale, double maximum)
    {
       return std::ceil(maximum / scale); // Fails on exact multiples
    }

This is wasteful:

    int get_array_size(double, scale, double maximum)
    {
       return 1 + std::ceil(maximum / scale); // Allocates extra array memory
    }

This is ugly and I am not sure if it is correct:

    int get_array_size(double, scale, double maximum)
    {
       if (maximum % scale == 0) // I am not sure if this is correct
          return 1 + std::ceil(maximum / scale);
       else
          return std::ceil(maximum / scale); // Maybe I can eliminate the call to std::ceil?
    }

I am trying to get the value maximum / scale on every open ended interval ending at multiples of scale and 1 + maximum / scale on every interval from >= multiple of scale ending at < multiple of scale + 1. I am not sure how to correctly express this in mathematical terms or how to implement it in c++. I would be grateful if someone can clarify my understand and point me in the right direction.

Mathematically I think I am trying to define f(x, s) = y st if s * n <= x and x < s * (n + 1) then y = n + 1. I want to implement this efficiently and respect the difference between <= and < comparison.

The way I interpret this question, I think maximum and scale don't actually matter - what you are really asking about is how to correctly map from floats to ints with specific boundary conditions. For example [0.0, 1.0) to 0, [1.0, 2.0) to 1, etc. So the question becomes a bit simpler if we just consider maximum / scale to be a single quantity; I'll call it t .

I believe you actually want to use std::floor instead of std::ceil :

int scaled_coord_to_index(float t) {
    return std::floor(t);
}

And the size of your array should always be the maximum scaled coordinate + 1 (with negative values normalized to start at 0).

int array_size(float min_t, float max_t) {
    // NOTE: This will "anchor" your coords based on the most negative value.
    //       e.g. if that value is 1.6, then your bins will be [1.6, 2.6), [2.6, 3.6), etc.
    //       To change that behavior you could use std::floor(min_t) instead.
    return scaled_coord_to_index(max_t - min_t) + 1;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM