不好意思,作業應該要自己做的,
但是有筆測資輸出了我怎麼想都想不出來的結果。
https://i.imgur.com/vYuDM5e.png
怕格式亂掉 貼截圖。
題目是要算組合 C n取k。
我一開始是先把分子跟分母分別算出來之後在相除,但這題有限制不能overflow。
於是圖片上的做法我的想法就是假設C5取2,就是1*(5/2*4/1),但是因為只能夠改函式部分
,cin的n,k,m一開始就是int,所以我在函式計算裡面強制把n以及k轉換成double。
問題來了,輸入了一堆測資大部分都正確,結果C 8取3出錯,正確應該是56,但是輸出結果
跑出了55這樣的奇妙結果,百思不得其解這個數字到底怎麼跑出來的,所以想請各位幫我看
哪裡出了問題。
真神奇,我自己試出來也是 55,很肯定是從 double轉成 long long 的問題,但是解釋不出理由用 float 的話就沒錯
浮點數的運算都是有誤差的,不然你把每一輪的c用double型態印出來看
作者:
oToToT (å±å©)
2018-11-22 01:47:00return c+0.5應該就好了
作者:
ckc1ark (偽物)
2018-11-22 01:49:00c會是55.99999999999999289457
rounding error,所以有沒有誤差跟數字大小未必有關那 rounding error 會愈運算差愈多,所謂的誤差傳遞
作者:
ckc1ark (偽物)
2018-11-22 01:50:00建議用8/1*7/2*6/3 這樣整數除法不會出問題 只怕太大而已
這也就是為什麼你直接把 56.0 轉過去會對,但用運算的方式會錯就是。clark大指的是 8*7*6/1/2/3 吧
請問一下為什麼不用遞迴做top down, 怕太慢就從下build up起來就好了C(n, m) = C(n – 1, m – 1) + C(n – 1, m)
他馬的大大說的就是 dynamic programming 解
這公式高中就交過了吧 這樣不會超過ㄅDP難的地方是從問題找遞迴
作者:
ckc1ark (偽物)
2018-11-22 01:57:008/1*7/2*6/3沒錯 過程中都會是整數
n*m的陣列從0,0開始算到n,m 作業試試這樣寫 不行的話遞迴慢慢做也行
喔喔 是我誤會clark大的意思ㄌ順便提醒一下這種題目測資範圍會影響解法的一定要給,不然就不是好題目
for i=1; i<=n; p *= (m-i+1)/i; Cm取n的話這樣就好噢抱歉推文有寫了 請忽略