2016-06-21 93 views
5

我有一段代碼,我把兩個數相乘,但條件是沒有那些整數應該是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代替。有沒有更好的方法來做到這一點。

+2

不這樣做'x? z? x * z:x:z? z:1' –

+2

您是試圖避免在句法級別使用「if」,或者您對生成的機器代碼中的分支感到厭倦?因爲所有使用'?'的解決方案只是將分支隱藏在地毯下(「if」仍然存在,您只是用不同的語法僞裝它)。 –

+0

怎麼了:'assert(x!= 0); assert(z!= 0);'並確保斷言不會觸發?換句話說,你爲什麼接受虛假數據?爲什麼不強行拒絕錯誤的數據?最後是:'y = x * z; if(y == 0)y = 1;'只檢查結果,不檢查操作數?如果答案是'x == 0 && z == 2',那麼'y'中的值應該是2,那麼你應該在問題中多說。 –

回答

1

如果他們中的一個是0那麼除了會給你同樣的結果,如果你改變01

y = (x * z > 0 ? x * z : x + z) 
+2

如果x和z均爲0,則不適用 –

+1

如果x或z爲負值,則以上方法無效。它應該是'y =((x * z == 0)?x + z:x * z)' –

15

下面

y=(x==0?1:x)*(z==0?1:z) 

會給你這個[ assembly ]代碼。


@Jerry Coffin的評論借來的適應他[ answer ]

y=(x+(x==0))*(z+(z==0)); 

會給你這個[ assembly ]代碼。

+1

生成最小的[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

+0

@Viatorus:更新了答案。 :) – sjsam

+0

mmm。你應該檢查最小的裝配-O2 ... –

6

我誠實地懷疑你可能會想出一個明顯表現不佳的方法。選擇一些你可以閱讀的東西,而不是你認爲最快的東西。有可能這種具體的操作不會成爲瓶頸。

+1

或者他正在尋找簡潔明瞭的代碼,在這種情況下,你的評論並沒有多大幫助。 –

+2

我向您挑戰,要通過明顯的雙條件解決方案來量化「清晰簡潔」解決方案的可讀性優勢。 – zneak

9
y = (!x^x) * (!z^z); 

這是有效的,因爲當你用0代表一個數字時,你會得到相同的數字。因此,如果x != 0,那麼!x == 0!x^x相當於0^x,即x。如果x == 0,然後!x == 1!x^x相當於1^0,這是1

+5

加1可滿足所有要求,對於任何在現實生活中實際編碼的人來說都是-999。 –

+0

與@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

+0

@Viatorus:就性能而言,生成的彙編指令的數量通常是無用的指標。編譯器通常有兩個互斥的標誌,用於快速和小型代碼。 –

3

我當然不會去保證它必須在代碼中的任何積極影響,但有可能會是這樣的:

x += int(x == 0); 
z += int(z == 0); 

此變量進行比較,以0,產生falsetrue。然後將其轉換爲int,如果值先前爲非零,則爲0,如果爲零,則爲1。然後我們將該結果添加到變量中,所以如果它是零,我們將添加一個,給出1.如果它是任何非零值,我們將它加0,這顯然不會影響它的值。

+1

或......''x + =!x;' –

+0

不錯,但我不認爲我們希望在這裏修改這個變量,儘管他們提到'我需要將它變成1'。這個改變只是爲了操作。 – sjsam

+0

@CareyGregory:不錯! – sjsam

2
y=max(x,1)*max(z,1); 

如果由#define預處理關鍵字或作爲正常功能必要定義max函數。

-2

如果您關注的是準確的結果,那麼您應該像大多數人所暗示的那樣,使用您的評論中的if語句或三元運算符?
如果你只是關心有在的代碼,你可以隨時OR 1本節沒有分支:

x = x | 1; 
z = z | 1; 
y = x * z; 

這將保證會有這個代碼,並且也不xz是每一個無枝等於0。但付出的代價是精確的,因爲你總是可以意外添加1要麼xz

00000000 | 1 = 1 
10001011 | 1 = 10001011 
10101010 | 1 = 10101011 <- imprecision introduced! 
+6

2 * 2 == 9是一個不精確的位。 –

1

它將工作

Y =(X X:1)?*(Z Z: 1)

0

那麼,我使用鏈接從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); 
} 
相關問題