Что представляет собой постоянная 0,0039215689?


310

Я постоянно вижу эту константу, всплывающую в различных графических заголовочных файлах

0.0039215689

Кажется, это как-то связано с цветом?

Вот первый хит в Google :

void RDP_G_SETFOGCOLOR(void)
{
    Gfx.FogColor.R = _SHIFTR(w1, 24, 8) * 0.0039215689f;
    Gfx.FogColor.G = _SHIFTR(w1, 16, 8) * 0.0039215689f;
    Gfx.FogColor.B = _SHIFTR(w1, 8, 8) * 0.0039215689f;
    Gfx.FogColor.A = _SHIFTR(w1, 0, 8) * 0.0039215689f;
}

void RDP_G_SETBLENDCOLOR(void)
{
    Gfx.BlendColor.R = _SHIFTR(w1, 24, 8) * 0.0039215689f;
    Gfx.BlendColor.G = _SHIFTR(w1, 16, 8) * 0.0039215689f;
    Gfx.BlendColor.B = _SHIFTR(w1, 8, 8) * 0.0039215689f;
    Gfx.BlendColor.A = _SHIFTR(w1, 0, 8) * 0.0039215689f;

    if(OpenGL.Ext_FragmentProgram && (System.Options & BRDP_COMBINER)) {
        glProgramEnvParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 2, Gfx.BlendColor.R, Gfx.BlendColor.G, Gfx.BlendColor.B, Gfx.BlendColor.A);
    }
}

//...more like this

Что означает это число? Почему никто, кажется, не объявляет это как const?

Я не смог найти в Google ничего, что могло бы это объяснить.


16
Есть ли какая-то причина, по которой исходный код написал бы это вместо (1.f/255)?
— MM

53
Мммм ... если бы был какой-то способ избежать магических чисел ...
— Пол Дрейпер

12
1/255 == 0.00(3921568627450980)- Парены означают повторение.
— Jfs

82
Со своим следующим магическим номером попробуйте спросить Wolfram Alpha
— AakashM

12
по какой бы то ни было причине, использование магического числа без документирования его назначения очень не круто
— Исаак Рабинович,

Ответы:


378

0.0039215689примерно равно 1/255.

Видя, что это OpenGL, производительность, вероятно, важна. Так что, вероятно, можно догадаться, что это было сделано из соображений производительности.

Умножение на обратное происходит быстрее, чем повторное деление на 255.


Примечание:

Если вам интересно, почему такая микрооптимизация не оставлена ​​на усмотрение компилятора, это потому, что это небезопасная оптимизация с плавающей запятой. Другими словами:

x / 255  !=  x * (1. / 255)

из-за ошибок округления с плавающей точкой.

Таким образом, хотя современные компиляторы могут быть достаточно умны, чтобы выполнить эту оптимизацию, им не разрешается делать это, если вы явно не скажете им об этом с помощью флага компилятора.

Связанный: Почему GCC не оптимизирует a * a * a * a * a * a к (a * a * a) * (a * a * a)?


10
Я действительно не знал, что это было, когда я впервые увидел это. Но, видя, как он использовался, я подозревал, что это была оптимизация, умноженная на взаимность. Так что я проверил свой калькулятор и, конечно же, я догадался.
— Мистика

55
Я бы ожидал увидеть это как a = b * (1.0f / 255); компиляторы все еще делают постоянное свертывание, не так ли?
— Илмари Каронен,

9
@IlmariKaronen Да, они все еще делают постоянное сворачивание. На самом деле это требуется для некоторых вещей, таких как разрешения шаблонов и тому подобное. Но я бы просто вытащил это как константу или макрос. Но, эй, не весь код написан идеально. :)
— Mysticial

5
@hippietrail Изначально мне было интересно то же самое. Но если вы используете 256, он будет масштабироваться 0.0 - 0.996вместо желаемого 0.0 - 1.0. ( 0.996 = 255/256где 255наибольшее 8-разрядное целое число)
— Mysticial

7
И, конечно же, чтобы ответить на мой собственный вопрос, это потому, что два других числа не могут быть представлены как стандартные числа с плавающей запятой. Следующее значение ниже 0,0039215689 - 0,0039215684.
— Даниэль Вахтер

79

Это умножение на 0.0039215689fпреобразует целочисленную интенсивность цвета в диапазоне от 0 до 255 в реальную интенсивность цвета в диапазоне от 0 до 1.

Как указывает Илмари Каронен, даже если это оптимизация, она довольно плохо выражена. Было бы намного яснее умножить на (1.0f/255).


5
Или, может быть, лучше, определяется как константа?
— Джонни

9
@Johny Определено как константа. Дело не в волшебной ценности.
— Дэвид Хеффернан
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.