Round a Vector3 to the nearest power of 3

I have never needed to do this before, and cannot find much information on it.
Is there any way to round each float in a Vector3 to the nearest power of 3?

e.g. : 3, 6, 9, 12, 15, 18, 21, 24…

So a Vector3 of (3.8f, 8.0f, 1.4f) would round to (3.0f, 9.0f, 0f)

using UnityEngine;
using System.Collections;

public class DivisableBy : MonoBehaviour {

    public Vector3 test;

    void Start ()
    {
        DivisableByThree(test);
    }
   
    Vector3 Three(Vector3 vec)
    {
        Vector3 vector;
        if(vec.x %3 == 0)
            vector.x = vec.x;
        else
        {
            vector.x = Mathf.Round(vec.x/3f);
            if (vector.x == 0f && vec.x > 0f) vector.x += 1f;
            vector.x *= 3f;
        }
        if(vec.y %3 == 0)
            vector.y = vec.y;
        else
        {
            vector.y = Mathf.Round(vec.y/3f);
            if (vector.y == 0f && vec.y > 0f) vector.y += 1f;
            vector.y *= 3f;
        }
        if(vec.z %3 == 0)
            vector.z = vec.z;
        else
        {
            vector.z = Mathf.Round(vec.z/3f);
            if (vector.z == 0f && vec.z > 0f) vector.z += 1f;
            vector.z *= 3f;
        }
        Debug.Log(vector);
        return vector;
    }
}

or better:

using UnityEngine;
using System.Collections;

public class DivisableBy : MonoBehaviour {

    public Vector3 test;

    void Start ()
    {
        Debug.Log (MakeVectorDivisableBy(test, 3));
    }

    public static float MakeDivisableBy(float input, int divide)
    {
        if(input % divide == 0)
            return input;
        else
        {
            float x = Mathf.Round(input/divide);
            if (x == 0f && input > 0f) x += 1f;
                x *= divide;
            return x;
        }
    }
    public static Vector3 MakeVectorDivisableBy(Vector3 vec, int divide)
    {
        Vector3 vector = new Vector3(MakeDivisableBy(vec.x, divide), MakeDivisableBy(vec.y, divide), MakeDivisableBy(vec.z, divide));
        return vector;
    }
}

The values you’ve listed aren’t powers but multiples, so this one usually helps:

int GetMultiple(float x, int multipleOf)
{
    return ((int)((x / multipleOf) + 0.5f)) * multipleOf;
}

Note, that there are a few edge cases due to float precision, for example when:
x = (y + 0.5)*multipleOf where y is a integer
Example:
x = 10.5
You probably expect 12, but you may also get 9 if
(10.5/3 +0.5) is something like 3.49999 + 0.5 = 3.9999 (casted to an int it’s 3).

1 Like

you could better use

public static float MakeDivisableBy(float input, int divide)
{
    if(input % divide == 0)
        return input;
    else
    {
        float x = Mathf.Round(input/divide)*divide;
        return x;
    }
}

then, but that doesn’t check for 0.