給定兩個浮點數,我在尋找高效的方法來檢查它們是否具有相同的符號的兩個值爲零(+0.0或-0.0),則應該認爲它們具有相同的符號。如何在處理負零時有效比較兩個浮點值的符號
例如,
- SameSign(1.0,2.0)應返回true
- SameSign(-1.0,-2.0)應返回true
- SameSign(-1.0,2.0)應該返回false
- SameSign(0.0,1.0)應返回true
- SameSign(0.0,-1.0)應返回true
- SameSign(-0.0,1.0)應返回true
- SameSign(-0.0,-1.0)應返回true
C++中的幼稚,但正確實施SameSign
是:
bool SameSign(float a, float b)
{
if (fabs(a) == 0.0f || fabs(b) == 0.0f)
return true;
return (a >= 0.0f) == (b >= 0.0f);
}
假設IEEE浮點模型,這裏的編譯爲網點代碼的SameSign
的變體(至少用Visual C++ 2008):
bool SameSign(float a, float b)
{
int ia = binary_cast<int>(a);
int ib = binary_cast<int>(b);
int az = (ia & 0x7FFFFFFF) == 0;
int bz = (ib & 0x7FFFFFFF) == 0;
int ab = (ia^ib) >= 0;
return (az | bz | ab) != 0;
}
與binary_cast
定義如下:
template <typename Target, typename Source>
inline Target binary_cast(Source s)
{
union
{
Source m_source;
Target m_target;
} u;
u.m_source = s;
return u.m_target;
}
我在尋找兩件事情:
更快,更有效的實現的
SameSign
,使用位技巧,FPU技巧甚至SSE內在因素。將
SameSign
有效延伸至三個值。
編輯:
我做了對的SameSign
的三種變體(在原來的問題描述的兩個變種,加上斯蒂芬的一個)的一些性能測量。每個函數運行200-400次,在101個浮點數的所有連續值對中隨機填充-1.0,-0.0,+0.0和+1.0。每次測量重複2000次,並保持最短時間(以清除所有緩存效應和系統誘導的減速)。該代碼是使用Visual C++ 2008 SP1進行編譯的,並且已啓用最大化優化和SSE2代碼生成。測量是在Core 2 Duo P8600 2.4 Ghz上完成的。
這裏有定時,不計算從陣列獲取的輸入值,調用函數和檢索結果(其量以6-7 clockticks不等)的開銷:
- 樸素變體:15蜱
- 位魔術變型:13蜱
- 斯蒂芬斯的變體:6蜱
任何特定的語言/平臺? – 2010-05-27 15:50:43
嘿,謝謝你的好問題:)最好是x86上的C/C++。 – 2010-05-27 15:54:01
[比較兩個浮點數以查看它們是否都是負數,或者兩個都是正數]可能有重複。(http://stackoverflow.com/questions/2013680/comparing-two-floats-to-see-if-theyre-both -negative-or-both-positive) – ChrisF 2011-07-12 15:05:33