views:

61

answers:

3

I need to implement a function which normalizes coordinates. I define normalize as (please suggest a better term if Im wrong):

Mapping entries of a data set from their natural range to values between 0 and 1.

Now this was easy in one dimension:

    static List<float> Normalize(float[] nums)
    {
        float max = Max(nums);
        float min = Min(nums);
        float delta = max - min;

        List<float> li = new List<float>();
        foreach (float i in nums)
        {
            li.Add((i - min) / delta);
        }
        return li;
    }

I need a 2D version as well and that one has to keep the aspect ratio intact. But Im having some troubles figuring out the math.

Although the code posted is in C# the answers need not to be.

Thanks in advance. :)

A: 

If I understand correctly, you want to map points to the square [(0,0), (1,0), (0,1), (1,1)]. Let max_xy be the maximum of both the x and the y values, and similarly for min_xy. Use those values to calculate delta. Compute two offsets, one for x and one for y.

Since you're dividing by the same delta, the aspect ratio is preserved.

offset = min == 0f ? 0 : -min is unnecessarily long by the way. What is -0?

larsmans
I removed the offset, thanks. Example input (1D): [2, 4, 6, 8, 10]. Output: [0, 0.25, 0.5, 0.75, 1]. Ill try using the same max and min for all dimensions, thanks.
mizipzor
+1  A: 

Simple idea: Find out which dimension is bigger and normalize in this dimension. The second dimension can be computed by using the ratio. This way the ratio is kept and your values are between 0 and 1.

kasten
You mean I should calculate *delta* for both dimensions and use the higher number during the normalization of both?
mizipzor
Yep that does the same and is even simpler :).
kasten
+4  A: 

It seems you want each vector (1D, 2D or ND) to have length <= 1.
If that's the only requirement, you can just divide each vector by the length of the longest one.

double max = maximum (|vector| for each vector in 'data');
foreach (Vector v : data) {
    li.add(v / max);
}

That will make the longest vector in result list to have length 1.

But this won't be equivalent of your current code for 1-dimensional case, as you can't find minimum or maximum in a set of points on the plane. Thus, no delta.

Nikita Rybak
Beat me to it :)
ChrisF
Hm. Maybe I made a bad call wanting the lowest value at 0 and the highest at 1. I assume this is usually the prefered way of normalizing coordinates?
mizipzor
@mizipzor You can choose a vector to be zero and subtract it from every vector in input. Say, you have (0, 1), (1, 0) and (2, 2) and get (0, 0), (1, -1), (2, 1) by moving first vector to zero.
Nikita Rybak
@mizipzor But my point is: there're so many ways of 'moving' set of vectors into a circle of radius one, that "the best method" simply doesn't exist.
Nikita Rybak
@mizipzor I think I've misread your comment. Yes, you can't compare multidimensional vectors to scalar numbers (like zero).
Nikita Rybak
@Nikita - I think the OP has to clarify if he wants the longest vector to be normalized to 1 (thus all vectors are bounded in a unit circle), or does he want the longest vector component to be bound to 1 (thus all vectors are bounded in the unit square). Additionally, there is a difference if the normalized coordinates span from -1 to 1 or from 0 to 1.
ysap