2012-01-16 25 views
5

Về cơ bản cho những thứ như thế này (không mã thực):Có an toàn khi nhân một phao/đôi bằng 0,5 thay vì chia cho 2 trong C# và C++ không?

for(int i = 0; i < 1000000000; ++i) 
{ 
    Vert v0 = mesh.polygons[i].edges[0].vert0; 
    Vert v1 = mesh.polygons[i].edges[0].vert1; 

    Vector3 center = (v0.pos + v1.pos)/2; 
} 

v0.pos là loại Vector3<float, float, float>, nhưng có thể Vector3<double, double, double>.

có an toàn không chỉ làm ?:

Vector3 center = (v0.pos + v1.pos) * 0.5; 

này có vẻ như tối ưu hóa sớm nhưng điều này có được càng nhanh càng tốt sẽ được kêu gọi hàng tỷ điểm (đám mây điểm).

+6

Điều gì sẽ xảy ra khi bạn đo lường hiệu suất của cả hai lựa chọn? Bạn không thể nói về tối ưu hóa ở cấp độ này mà không có * đo * kết quả trên nền tảng mục tiêu của bạn. –

+0

Đo lường theo cách này. Nhưng trình biên dịch của bạn 'nên' đã hoàn nguyên về bit-shifting để chia cho 2. – CaffGeek

+1

Đồng ý với Greg. Ngoài ra, hãy nhớ rằng bạn nên tập trung vào tính đúng đắn trước tốc độ.Phần lớn thời gian, trình biên dịch sẽ tối ưu hóa phần lớn điều này cho bạn (đặc biệt là khi bạn sử dụng chữ). – TheBuzzSaw

Trả lời

3

Không phải là một C++ chuyên gia bằng bất kỳ phương tiện, nhưng trong C#, làm điều này:

var a = new Func<float, float, double>((float f1, float f2) => (f1 + f2) * 0.5); 
var b = new Func<float, float, double>((float f1, float f2) => (f1 + f2)/2); 

tạo IL rằng trong cựu:

  1. tải các đối số
  2. Thêm họ (sản xuất một duy nhất)
  3. Chuyển kết quả thành một đôi
  4. Tải đối số kép (0.5)
  5. sẽ nhân đôi (sản xuất một đôi)
  6. Trả kết quả

và sau

  1. tải các đối số
  2. Thêm họ (sản xuất một đơn)
  3. tải các số nguyên không đổi (2)
  4. Chia (tạo một đĩa đơn, vì đơn/số nguyên tạo thành một đơn)
  5. Chuyển đổi kết quả để một đôi
  6. Trả về kết quả

Nó tấn công tôi rằng cựu khả năng sẽ có độ chính xác cao hơn vì các nhân được thực hiện trên 2 đôi, dẫn đến độ chính xác gấp đôi, trong khi ở sau này phân chia được thực hiện trên một đĩa đơn được upcast đến một đôi (nhưng vẫn chỉ sẽ có độ chính xác của đĩa đơn).

này mang tôi ra:

Console.Out.WriteLine(((double)1) * ((double)1/3)); 
Console.Out.WriteLine((1)/((float)3)); 

sản xuất:

0.333333333333333 
0.3333333 

Vì vậy, 'an toàn', có lẽ, nếu mất độ chính xácđạt được độ chính xác thêm là ok.

+0

*" 5. Chuyển đổi kết quả thành đôi "*: Các đại biểu đó là' Func 'bởi cơ hội nào? – Groo

+0

Vâng, xin lỗi, bản sao xấu về phía tôi ... Đã sửa lỗi. –

+0

Đúng và đủ, nhưng dường như với tôi rằng câu hỏi là liệu việc thay đổi phép chia thành phép nhân có thể thay đổi kết quả hay không (giả sử cùng một đầu vào cho cả hai), trong trường hợp này tôi không thấy nó như thế nào trường hợp. tức là đúc (f1 + f2) để tăng gấp đôi trước khi chia hoặc 0,5 để nổi và kết quả phải giống hệt nhau – Voo

Các vấn đề liên quan