Що являє собою константа 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)?
ММ

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 to (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-бітове ціле число)
містичне

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.