2009-03-01 32 views
6

Giả sử tôi có một float trong phạm vi [0, 1] và tôi muốn định lượng và lưu trữ nó trong một byte chưa ký. Nghe có vẻ như không có trí tuệ, nhưng trên thực tế nó khá phức tạp:Chuyển đổi/Định lượng Phạm vi Phao thành Dải số

Các giải pháp rõ ràng trông như thế này:

unsigned char QuantizeFloat(float a) 
{ 
    return (unsigned char)(a * 255.0f); 
} 

này hoạt động trong chừng mực mà tôi nhận được tất cả các số từ 0 đến 255, nhưng sự phân bố của các số nguyên thậm chí không. Hàm chỉ trả về 255 nếu đúng là 1.0f. Không phải là một giải pháp tốt.

Nếu tôi làm tròn thích hợp Tôi chỉ chuyển vấn đề:

unsigned char QuantizeFloat(float a) 
{ 
    return (unsigned char)(a * 255.0f + 0.5f); 
} 

Đây là kết quả 0 chỉ bao gồm một nửa số float tầm xa hơn bất kỳ số nào khác.

Làm cách nào để thực hiện việc lượng tử hóa với phân bố bằng nhau của phạm vi dấu chấm động? Lý tưởng nhất là tôi muốn có được sự phân bố bằng nhau của các số nguyên nếu tôi định lượng các float ngẫu nhiên phân bố đều nhau.

Bất kỳ ý tưởng nào?


Btw: Ngoài ra mã của tôi nằm trong C vấn đề là ngôn ngữ bất khả tri. Đối với những người không phải là C: Chỉ cần giả sử rằng chuyển đổi float sang int cắt phao.

EDIT: Vì chúng tôi đã có một số nhầm lẫn ở đây: Tôi cần ánh xạ ánh xạ float đầu vào nhỏ nhất (0) tới ký hiệu unsigned char nhỏ nhất và float cao nhất trong phạm vi của tôi (1.0f). (255).

Trả lời

10

Làm thế nào về a * 256f bằng séc để giảm 256 đến 255? Vì vậy, một cái gì đó như:

return (unsigned char) (min(255, (int) (a * 256f))); 

(Đối với một hàm min phù hợp trên nền tảng của bạn - Tôi không thể nhớ những chức năng C cho nó.)

Về cơ bản bạn muốn chia phạm vi thành 256 phần bằng nhau, mà là những gì nên làm. Trường hợp cạnh cho 1.0 đi tới 256 và yêu cầu làm tròn xuống chỉ vì miền được bao gồm ở cả hai đầu.

+0

wow - vâng, đó là nó! –

+0

Có - (unsigned char) (a * 256.0f) cung cấp cho bạn chính xác những gì bạn muốn cho mọi giá trị đầu vào ngoại trừ 1.0.C không có chức năng min tích hợp, vì vậy bạn sẽ phải tự viết nếu bạn chưa có. –

+0

John, tôi đã đưa ra kết quả tương tự, không thể chuyển nó chính xác từ bảng tính Excel. Tôi đã xóa câu trả lời đáng hổ thẹn của mình. – cdonner

1

Tôi nghĩ rằng những gì bạn đang tìm kiếm là thế này:

unsigned char QuantizeFloat (float a) 
{ 
    return (unsigned char) (a * 256.0f); 
} 

này sẽ ánh xạ giá trị float thống nhất trong [0, 1] để giá trị byte thống nhất trong [0, 255]. Tất cả các giá trị trong [i/256, (i + 1)/256 [(không bao gồm (i + 1)/256), với i trong 0..255, được ánh xạ tới i. Những gì có thể không mong muốn là 1.0f được ánh xạ tới 256.0f kết thúc tốt đẹp tới 0.

0

Người ta có thể truyền lỗi một lần dọc theo toàn bộ phạm vi trong khi duy trì phân phối bằng nhau như bạn sẽ nhảy vọt vào ngày 31 tháng 12 .

limit = 4 
maxi = limit - 1 

n = 16 
for i in range(n): 
    x = i/(n - 1) 

    a = x * maxi # Wrong distribution 
    b = x * limit # One off 
    c = x * (limit - 1/limit) 

    print(f"{x:.3f} | {a:.3f} | {b:.3f} | {c:.3f}") 

-

0.000 | 0.000 | 0.000 | 0.000 
0.067 | 0.200 | 0.267 | 0.250 
0.133 | 0.400 | 0.533 | 0.500 
0.200 | 0.600 | 0.800 | 0.750 
0.267 | 0.800 | 1.067 | 1.000 
0.333 | 1.000 | 1.333 | 1.250 
0.400 | 1.200 | 1.600 | 1.500 
0.467 | 1.400 | 1.867 | 1.750 
0.533 | 1.600 | 2.133 | 2.000 
0.600 | 1.800 | 2.400 | 2.250 
0.667 | 2.000 | 2.667 | 2.500 
0.733 | 2.200 | 2.933 | 2.750 
0.800 | 2.400 | 3.200 | 3.000 
0.867 | 2.600 | 3.467 | 3.250 
0.933 | 2.800 | 3.733 | 3.500 
1.000 | 3.000 | 4.000 | 3.750 
Các vấn đề liên quan