[問題] 大一程式設計作業請教

作者: mpyh12345 (嘉義金城武)   2018-11-22 01:29:04
不好意思,作業應該要自己做的,
但是有筆測資輸出了我怎麼想都想不出來的結果。
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這樣的奇妙結果,百思不得其解這個數字到底怎麼跑出來的,所以想請各位幫我看
哪裡出了問題。
作者: alan23273850   2018-11-22 01:40:00
真神奇,我自己試出來也是 55,很肯定是從 double轉成 long long 的問題,但是解釋不出理由用 float 的話就沒錯
作者: TMDTMD2487 (ㄚ冰)   2018-11-22 01:45:00
浮點數的運算都是有誤差的,不然你把每一輪的c用double型態印出來看
作者: alan23273850   2018-11-22 01:47:00
https://goo.gl/5vCq8X 這邊有人有嘗試過
作者: oToToT (屁孩)   2018-11-22 01:47:00
return c+0.5應該就好了
作者: ckc1ark (偽物)   2018-11-22 01:49:00
c會是55.99999999999999289457
作者: alan23273850   2018-11-22 01:49:00
rounding error,所以有沒有誤差跟數字大小未必有關那 rounding error 會愈運算差愈多,所謂的誤差傳遞
作者: ckc1ark (偽物)   2018-11-22 01:50:00
建議用8/1*7/2*6/3 這樣整數除法不會出問題 只怕太大而已
作者: alan23273850   2018-11-22 01:50:00
這也就是為什麼你直接把 56.0 轉過去會對,但用運算的方式會錯就是。clark大指的是 8*7*6/1/2/3 吧
作者: TMDTMD2487 (ㄚ冰)   2018-11-22 01:53:00
請問一下為什麼不用遞迴做top down, 怕太慢就從下build up起來就好了C(n, m) = C(n – 1, m – 1) + C(n – 1, m)
作者: alan23273850   2018-11-22 01:55:00
他馬的大大說的就是 dynamic programming 解
作者: TMDTMD2487 (ㄚ冰)   2018-11-22 01:56:00
這公式高中就交過了吧 這樣不會超過ㄅDP難的地方是從問題找遞迴
作者: ckc1ark (偽物)   2018-11-22 01:57:00
8/1*7/2*6/3沒錯 過程中都會是整數
作者: TMDTMD2487 (ㄚ冰)   2018-11-22 01:59:00
n*m的陣列從0,0開始算到n,m 作業試試這樣寫 不行的話遞迴慢慢做也行
作者: alan23273850   2018-11-22 02:54:00
喔喔 是我誤會clark大的意思ㄌ順便提醒一下這種題目測資範圍會影響解法的一定要給,不然就不是好題目
作者: IcecreamHsu (冰淇淋)   2018-11-23 02:08:00
for i=1; i<=n; p *= (m-i+1)/i; Cm取n的話這樣就好噢抱歉推文有寫了 請忽略

Links booklink

Contact Us: admin [ a t ] ucptt.com