作者EdisonX (閉上眼的魚)
看板C_and_CPP
標題[問題] uBig 設計模式
時間Mon Dec 17 02:42:11 2012
我承認有 re-develope ,不過主要是拿來練習用,
問題主要是 C 轉成 C++ 時,規劃很有問題。
另一個問題可能有得討論,
主要是 copy operator / constructor 帶來之 slide effect.
問題、敘述有點長,願拿出小弟一半 ptt 幣 (稅前 一萬 ) 以酬謝
(
http://ppt.cc/OCBA )
問 題 敘 述 <前言>
首先,我練習用 C 寫大數演算法,目前在 C 裡面已可以成功做幾個功能
(1) 大數 (+ - * / %) 整數
(2) 大數 (+ - * / %) 大數
然後在過程中,我發現一般網路上給的範例,function prototype
其實沒給正確 (當然我相信可能是因為只是 sample code 而已),
導致 function 沒辦法複用。
拿減法而言,一般給的 protype :
big_sub(int * A, int * B , int *C); /* C = A - B */
然後 size 是一般就事先定義好的,不然就是包成 struct,總之 prototype
不會有多一個引數叫 int size,作為 target。
但很尷尬的是,目前小弟做的大數除法,較有效率的做法,
prototype / caller 大概長這樣
big_sub(int * A , int * B, int * C , int size); /* prototype, C = A - B */
int R[r_size];
int A[DEF_SIZE], B[DEF_SIZE];
/* ...what ever... */
big_sub(A + c_len, R, B , r_len) /* caller */
就是因為上面上面粉紅色的部份,所以導致 prototype 讓我想重新設計。
然後又考慮到有些運算我不需要是 C = A - B,而是 C-=B,
所以我又要多寫了
big_subs(int * A , int * B , int size); /* A-=B */
轉到 C++ class 後,便是我地獄的開始...
問 題 敘 述 < Q1 轉到 C++ >
這裡我想先說一下 (我不確定後續發展有沒有關係),
我這份 class 打算做三個一樣的東西,
分別是 10 進位、萬進位、65536 進位,
然後陣列大小因為怕愈搞愈複雜,所以給的是固定大小的陣列 (不是 heap),
上述三個 class 就姑且稱 big10, big10000, big2n。
目前計畫是每個 class 都各自獨立,在寫 big10 的時候發現,
為了配合 operator + - * / ,所以這部份 prototype 根本不能塞 size 進去,
導致最後,原本在 C 寫好的 function, 全都塞到 class private 裡去,變成這樣
class ubig10{
private:
int arr[100];
/* C style functions */
void c_big_add(int * A , int * B, int * C , int size);
void c_big_adds(int * A , int * B, int size);
void c_big_add_int(int * A, int B , int * C , int size);
void c_big_adds_int(int * A, int B , int size);
/* ...whatever... */
public:
/* ... whatever ... */
/* friend every where */
friend ...
friend ...
};
oveload operator 是用 class member function,
不過一直在調用 C-style member function,
做成這樣讓我感覺很愚蠢,不知道是否有較佳之方案可解決?
然後, big10 / big10000 的部份 我在想 這麼做可能會較佳?
template<int base=10 , int len = 4>
class ubig10n{
/* ...what ever... */
};
這樣到時候要 base-10 、base-10000 都可以很快搞出來 (吧)
Q2 slide effect
我在網路上搜尋過一些各式各樣的 sample code (不專指大數),
然後 k 過手邊的書還是沒滿足我,
假設 class 裡有 heap 成員,最明顯的問題大概是長這樣吧
Class Class::func(const Class & A , Class & B){
Class tmpA(A) ; /* 不改 A , 暫存 A */
Class tmpB(B) ; /* B 需要兩份 */
/* ...whatever... */
return Class(tmpA - tmpB);
}
這裡在 tmpA / tmpB 的地方可能沒辦法避開 constructor ,
請問最後開銷是否是無法避免?
(1) 先將 tmpA - tmpB 結果存下來,假設叫 tmpV
(2) tmpV 再傳回去,呼叫 operator = , assigned to caller.
那如果
另一個 member function 裡,有一段是這樣的話
void Class::func2(const Class & A, Class & B) {
/* ...whatever... */
for(i=0; i<100; ++i) Class::func( A , B)
/* ...whatever... */
}
這樣不就代表暫存變數 tmpA、tmpB 之生死循環了 100 次,
代表這 100 次經歷了 allocate、initialize value、release memory,
感覺很花費時間,所以,如果遇到這種情況的話,
將 func 直接 copy-paste 到 func2 裡面可以避開沒錯,
但萬一呼叫 func2~func20 都一直在裡面呼叫 func 的話呢?
也是一樣 copy-paste 解決?不知道我想法哪裡出了問題。
---------------------------------
最後,謝謝各位耐心看完敘述,若上述敘述不清楚請點出,
我將再補充說明,謝謝各位先進不吝指導與賜教,感激不盡。
--
~ 這輩子與神手無緣
我只好當神獸了 ~
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 180.177.76.161
→ loveme00835:class 是從 ADT(Abstract Data Type) 演變而來的, 你 12/17 02:48
→ loveme00835:的介面都不夠抽象, 所以轉換會難轉是一定的 12/17 02:49
請教這部份可以怎做才是所謂的 ADT ? typedef int Big[BIG_SIZE] ??
→ loveme00835:可以參考 std::move() 並實作 move ctor 12/17 02:52
→ loveme00835:以及 move assignment 12/17 02:55
這兩個我有找過一下,粗略似乎不是件容易事,或許 k 個有問題再發文較有效率些,
先謝謝 loveme00835 :)
→ legnaleurc:你在運算時要把"陣列"這個概念丟掉, 不然一定不夠抽象 12/17 13:48
→ legnaleurc:理想的大數類別應該是個數值型別, 也就是 int 能做的 12/17 13:50
→ legnaleurc:運算你都用同樣的 prototype 做就好了 12/17 13:50
→ legnaleurc:之前給學弟練習 C++ 的範例, 隨便看看 12/17 14:00
我承認這裡有兩個 prototype 有點不懂
template< typename T > T to() const; /* 目的是 ? 轉型嗎? */
class Private; /* 這個我又更不懂了 */
然後關鍵的
operator / 我沒在上面看到,代表這部份當時可能沒實作 ?
去掉
operator / 很好實作,做得出來真的也不是問題,
但考慮到
operator / 真的不是很好實作
→ EdisonX:可能我等一下先整理一下除法部份,再丟上來討論會好點吧. 12/17 16:35
這是 c code 部份
http://codepad.org/u2Z0mi3v
關鍵在於要 效率不要太差 時,大數還要回到 array 慢慢細思?
我承認 ADT 做很鳥,在轉 operator + - * 時很順沒錯
(和 legnaleurc 給的 class prototype 相仿)
但為了完成將 ubig10_div_v1 轉到 operator /
中間有用到的四個 function 還是要塞 size 為佳,
因
過程中要做的可能是 A[7:2] -= B[10:5] 、類似的東西,
也就因為這層原因導致想不透怎轉過去
※ 編輯: EdisonX 來自: 180.177.76.161 (12/17 17:34)
推 legnaleurc:就再加個 class 代表 num/den 就好啦 ... 12/17 18:31
→ legnaleurc:看不太懂你的 annotation 是什麼意思 12/17 18:36
→ EdisonX:先感謝 lovme00835 與 legnaleurc,其餘我找時間imple. :) 12/19 00:50