我有一段代碼,我把兩個數相乘,但條件是沒有那些整數應該是0.如果它是0,我需要使其爲1,以便不計算在內。在C++中用'1'取代整數'0'的最佳方法
y=x*z // x>0, z>0. if x==0 then x=1, if z==0, then z=1;
我想避免「如果」條件檢查每個變量,並用1代替。有沒有更好的方法來做到這一點。
我有一段代碼,我把兩個數相乘,但條件是沒有那些整數應該是0.如果它是0,我需要使其爲1,以便不計算在內。在C++中用'1'取代整數'0'的最佳方法
y=x*z // x>0, z>0. if x==0 then x=1, if z==0, then z=1;
我想避免「如果」條件檢查每個變量,並用1代替。有沒有更好的方法來做到這一點。
如果他們中的一個是0
那麼除了會給你同樣的結果,如果你改變0
到1
y = (x * z > 0 ? x * z : x + z)
如果x和z均爲0,則不適用 –
如果x或z爲負值,則以上方法無效。它應該是'y =((x * z == 0)?x + z:x * z)' –
下面
y=(x==0?1:x)*(z==0?1:z)
會給你這個[ assembly ]代碼。
和@Jerry Coffin的評論借來的適應他[ answer ]
y=(x+(x==0))*(z+(z==0));
會給你這個[ assembly ]代碼。
生成最小的[Assembly](https://gcc.godbolt.org/#compilers :!( :G530,選項: ' - STD%的3Dc%2B%2B14 + -O3',源:「INT +主(INT + 1,+焦炭**克)%0A%7B%0A ++ INT + X +%3D + *克%5B0%5D%3B%0A ++ INT + Z +%3D + *克%5B1%5D%3B%0A ++返回+(x%的3D%3D0%3F1:X)*(Z%3D%3D0%3F1位:Z )%3B%0A%7D')),filterAsm:(commentOnly:噸,指令:!噸,標籤:噸),版本:3)。 – Viatorus
@Viatorus:更新了答案。 :) – sjsam
mmm。你應該檢查最小的裝配-O2 ... –
我誠實地懷疑你可能會想出一個明顯表現不佳的方法。選擇一些你可以閱讀的東西,而不是你認爲最快的東西。有可能這種具體的操作不會成爲瓶頸。
或者他正在尋找簡潔明瞭的代碼,在這種情況下,你的評論並沒有多大幫助。 –
我向您挑戰,要通過明顯的雙條件解決方案來量化「清晰簡潔」解決方案的可讀性優勢。 – zneak
y = (!x^x) * (!z^z);
這是有效的,因爲當你用0代表一個數字時,你會得到相同的數字。因此,如果x != 0
,那麼!x == 0
和!x^x
相當於0^x
,即x
。如果x == 0
,然後!x == 1
和!x^x
相當於1^0
,這是1
加1可滿足所有要求,對於任何在現實生活中實際編碼的人來說都是-999。 –
與@sjsam相比,需要兩個xor指令。 [組裝](https://gcc.godbolt.org/#compilers:!((編譯器:G530,選項: ' - STD%的3Dc%2B%2B14 + -O3',源:「INT +主(INT + 1, +焦炭**克)%0A%7B%0A ++ INT + X +%3D + *克%5B0%5D%3B%0A ++ INT + Z +%3D + *克%5B1%5D%3B%0A ++返回+( !X +%5E + X)+ * +(!Z +%5E + Z)%3B%0A%7D')),filterAsm:(commentOnly:T,指令:T,標籤:T),版本:3)。 – Viatorus
@Viatorus:就性能而言,生成的彙編指令的數量通常是無用的指標。編譯器通常有兩個互斥的標誌,用於快速和小型代碼。 –
我當然不會去保證它必須在代碼中的任何積極影響,但有可能會是這樣的:
x += int(x == 0);
z += int(z == 0);
此變量進行比較,以0,產生false
或true
。然後將其轉換爲int
,如果值先前爲非零,則爲0
,如果爲零,則爲1
。然後我們將該結果添加到變量中,所以如果它是零,我們將添加一個,給出1.如果它是任何非零值,我們將它加0,這顯然不會影響它的值。
y=max(x,1)*max(z,1);
如果由#define預處理關鍵字或作爲正常功能必要定義max函數。
如果您關注的是準確的結果,那麼您應該像大多數人所暗示的那樣,使用您的評論中的if語句或三元運算符?
。
如果你只是關心有在的代碼,你可以隨時OR 1本節沒有分支:
x = x | 1;
z = z | 1;
y = x * z;
這將保證會有這個代碼,並且也不x
或z
是每一個無枝等於0
。但付出的代價是精確的,因爲你總是可以意外添加1
要麼x
或z
:
00000000 | 1 = 1
10001011 | 1 = 10001011
10101010 | 1 = 10101011 <- imprecision introduced!
2 * 2 == 9是一個不精確的位。 –
它將工作
Y =(X X:1)?*(Z Z: 1)
那麼,我使用鏈接從this answer並創建了這樣的代碼。 assembly here,裝配較短,所以可能會更快,但需要分析,因爲裝配時間較短可能不會更快。
int main(int i, char**g)
{
int x = *g[0];
int z = *g[1];
int tmp = z ? 1 : z;
return (x==0?tmp:x*tmp);
}
不這樣做'x? z? x * z:x:z? z:1' –
您是試圖避免在句法級別使用「if」,或者您對生成的機器代碼中的分支感到厭倦?因爲所有使用'?'的解決方案只是將分支隱藏在地毯下(「if」仍然存在,您只是用不同的語法僞裝它)。 –
怎麼了:'assert(x!= 0); assert(z!= 0);'並確保斷言不會觸發?換句話說,你爲什麼接受虛假數據?爲什麼不強行拒絕錯誤的數據?最後是:'y = x * z; if(y == 0)y = 1;'只檢查結果,不檢查操作數?如果答案是'x == 0 && z == 2',那麼'y'中的值應該是2,那麼你應該在問題中多說。 –