HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Checking if vector is normalized

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
normalizedcheckingvector

Problem

I tried to check if my vector struct is normalized, and I ended up with this code:

public bool IsNormalized
{
    get
    {
        double len = Length; // Math.Sqrt ((X * X) + (Y * Y) + (Z * Z)); -- X, Y, Z are in double format

        const double min = 1 - 1e-14;
        const double max = 1 + 1e-14;

        return (len >= min && len <= max);
    }
}


Is this solution OK? I read double has 15 digits precision, but 1+1E-15 give 1, so I changed to E14.

Is this all good? I need best accuracy.

Solution

This seems ok, depending on how precise you want it to be (some margin of error will always be needed since this is floating-point, but how much will depend on your needs)

Alternatively, you could check Math.Abs(1 - len) < 1e-14, but I suspect the same precision problems will remain.

I was somewhat surprised that 1 + 1e-15 equals 1, though, because doubles have 52 bits of precision, which should be more than enough to store a difference of 15 digits (-log2(1/10^15) gives me around 49.8, which is less than 52 bits).

So I double checked and 1 - 1.0e-15 does not give me 1.

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(1 - 1.0e-15); //Does NOT print 1
        Console.Read();
    }
}


Same thing for 1 + 1.0e-15 (though this one is trickier)

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(1 + 1.0e-15); //Prints 1
        Console.WriteLine(1 + 1.0e-15 == 1); //...but this prints False
        Console.Read();
    }
}


I suspect Console.WriteLine is only printing a limited number of digits: less than the ones double can represent.

As a final note, Sqrt(1) == 1, so instead of using the Length you could use the SquaredLength and save a (potentially expensive) Sqrt operation.

Code Snippets

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(1 - 1.0e-15); //Does NOT print 1
        Console.Read();
    }
}
class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(1 + 1.0e-15); //Prints 1
        Console.WriteLine(1 + 1.0e-15 == 1); //...but this prints False
        Console.Read();
    }
}

Context

StackExchange Code Review Q#41732, answer score: 6

Revisions (0)

No revisions yet.