Hằng số 0,009215689 đại diện cho cái gì?


310

Tôi liên tục thấy điều này bật lên liên tục trong các tệp tiêu đề đồ họa khác nhau

0.0039215689

Nó dường như có một cái gì đó để làm với màu sắc có thể?

Đây là lần truy cập đầu tiên trên 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

Con số này thể hiện điều gì? Tại sao không ai tuyên bố nó là một const?

Tôi không thể tìm thấy bất cứ điều gì trên Google đã giải thích nó.


16
Có bất kỳ lý do nào mà mã nguồn sẽ viết điều này thay vì (1.f/255)?
MM

53
Mmmm ... nếu chỉ có một số cách để tránh các con số ma thuật ....
Paul Draper

12
1/255 == 0.00(3921568627450980)- parens có nghĩa là sự lặp lại.
jfs

82
Với số ma thuật tiếp theo của bạn, hãy thử hỏi Wolfram Alpha
AakashM

12
dù lý do là gì đi nữa, sử dụng một con số ma thuật mà không ghi lại mục đích của nó là rất không hay
Isaac Rabinovitch

Câu trả lời:


378

0.0039215689 xấp xỉ bằng 1/255 .

Thấy rằng đây là OpenGL, hiệu năng có lẽ rất quan trọng. Vì vậy, có thể an toàn để đoán rằng điều này đã được thực hiện vì lý do hiệu suất.

Nhân với đối ứng nhanh hơn chia nhiều lần cho 255.


Lưu ý bên:

Nếu bạn đang tự hỏi tại sao tối ưu hóa vi mô như vậy không để lại cho trình biên dịch, thì đó là vì nó là một tối ưu hóa dấu phẩy động không an toàn. Nói cách khác:

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

do lỗi làm tròn điểm nổi.

Vì vậy, trong khi các trình biên dịch hiện đại có thể đủ thông minh để thực hiện tối ưu hóa này, chúng không được phép thực hiện trừ khi bạn nói rõ ràng với chúng thông qua cờ trình biên dịch.

Liên quan: Tại sao GCC không tối ưu hóa a * a * a * a * a * a thành (a * a * a) * (a * a * a)?


10
Tôi thực sự không biết nó là gì khi lần đầu tiên nhìn thấy nó. Nhưng nhìn cách nó được sử dụng, tôi nghi ngờ đó là sự tối ưu hóa nhiều lần. Vì vậy, tôi đã kiểm tra trong máy tính của mình và chắc chắn - tôi đoán đúng.
Bí ẩn

55
Tôi đã mong đợi để xem nó được viết như a = b * (1.0f / 255); trình biên dịch vẫn làm liên tục gấp, phải không?
Ilmari Karonen

9
@IlmariKaronen Vâng, họ vẫn làm việc liên tục. Nó thực sự cần thiết cho một số thứ như độ phân giải mẫu và như vậy. Nhưng tôi sẽ chỉ lấy nó ra như một hằng số hoặc một macro. Nhưng này, không phải tất cả các mã được viết hoàn hảo. :)
Bí ẩn

5
@hippietrail Ban đầu, tôi đã tự hỏi điều tương tự. Nhưng nếu bạn sử dụng 256, nó sẽ mở rộng từ 0.0 - 0.996thay vì mong muốn 0.0 - 1.0. ( 0.996 = 255/256nơi 255có số nguyên 8 bit lớn nhất)
Mystical

7
Và tất nhiên, để trả lời câu hỏi của riêng tôi, đó là vì hai số còn lại không thể được biểu diễn dưới dạng số C tiêu chuẩn. Phao tiếp theo dưới 0,009215689 là 0,009215684.
Daniel Waechter

79

Phép nhân này bằng cách 0.0039215689fchuyển đổi cường độ màu có giá trị nguyên trong phạm vi 0 đến 255 thành cường độ màu có giá trị thực trong phạm vi 0 đến 1.

Như Ilmari Karonen chỉ ra, ngay cả khi đây là một sự tối ưu hóa thì nó cũng được thể hiện khá tệ. Nó sẽ rõ ràng hơn nhiều để nhân lên (1.0f/255).


5
Hoặc có thể tốt hơn, được định nghĩa là hằng số?
Johny

9
@Johny Chắc chắn được định nghĩa là một hằng số. Điểm không phải là một giá trị ma thuật.
David Heffernan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.