|
/*========================================================*/ <<<あゆしゃのC言語プログラミング>>> /*========================================================*/ 第470回 10進変換の高速化3 発行 2004年7月5日(月曜日) 発行数 約2800 {magclick} /*========================================================*/ はじめに ( 決り文句 ) /*========================================================*/ ・このメールマガジンは、主にまぐまぐさんから発行しています。 ・ジャンルは、マルチメディアのプログラム、C言語です。 ・横60文字で作成し、インデントは大抵半角スペース4つです。 ・ここで扱うプログラムは、C言語と半光年以内のものです。 ・登録解除は、メルマガのホームページでお願いします。 ・過去ログはバックナンバー(下欄参照)を活用して下さい。 ・内容は私が感じたもので、最新の技術も、へたれもあります。 ・わかりやすさを優先させる為、たまに嘘があるかもしれません。 ・セキュリティ突破のため、暗号化された単語があります。 /*========================================================*/ ご挨拶 /*========================================================*/ こんにちは。あゆしゃです。 先日、増勝選新の理論をページにまとめました。 http://ayusya.hp.infoseek.co.jp/ http://ayusya.hp.infoseek.co.jp/TetuIWCN.html ファイル名称に悩みましたが、 インクリーズド ウィン チョイス ニュー の頭文字としました。 /*========================================================*/ 株日記 /*========================================================*/ 野村のバーチャル株式投資倶楽部 http://www2.nomura.co.jp/vstock/VirtualServlet? (ゲストでログインして Ayusya を探せば成績を参照できます) ★ここ一週間の Ayusya の成績 木曜日 1,008,535円 金曜日 1,007,509円 月曜日 1,005,648円 火曜日 1,008,945円 木曜日 1,022,928円 24,864番 金曜日 1,026,300円 24,810番 そろそろ手入れをしようかなぁ、と思っただけ(笑) {magclick} /*========================================================*/ 今回のお題 << 10進変換の高速化3 >> /*========================================================*/ 前回、だいぶ早くなりました。 結果 0.240s もう少し、速くできる気がします。 CString CXInt10::toString( void ) { char buff[ SIZE10 + 1 ]; UCHAR* pch = m_buff + SIZE10 - 1; char* pb = &buff[ 0 ]; // 最大の桁位置を求める for( ; pch > m_buff; pch-- ) { if( *pch ) break; } // '0'を足しながらコピー for( ; pch >= m_buff; pch--, pb++ ) { *pb = ( char )*pch + '0'; } *pb = 0; return CString( buff ); } 最大の桁位置を求めたときに、長さを求めておき、 int len = pch - m_buff + 1; CString にするときに、それを指定すると、 return CString( buff, len ); CString が buff の長さを調べる必要がないだけ、strlen が 省略され、早くなるはずです。 結果 0.230s うーん、微妙? あとは。。。 CXInt10& CXInt10::mul( int b ) { UCHAR* pch = m_buff; UCHAR* pe = m_buff + min( SIZE10, GetLength() + 11 ); int c = 0; for( ; pch < pe; pch++ ) { c = ( int )*pch * b + c; *pch = ( UCHAR )( c % 10 ); c /= 10; } return *this; } 余りを求めているところ、割り算が2回発生しているのが もったいないです。 for( ; pch < pe; pch++ ) { c = ( int )*pch * b + c; int c2 = c / 10; *pch = ( UCHAR )( c - c2 * 10 ); c = c2; } 割り算が速いという前提で、余りの部分は割り算結果を10倍 したものを引くことでもとめましょう。 結果 0.200s うっ、予想以上に速くなりました! ・・・あれれ? CXInt10& CXInt10::add( CXInt10& b ) { ... for( ; pch < pe; pch++, pch2++ ) { c = ( int )*pch + ( int )*pch2 + c; *pch = ( UCHAR )( c % 10 ); if( c >= 10 ) c = 1; else c = 0; } return *this; } この関数のキャリーのところ、if にしたのですよね。 同じような方式に変えてみますか。 結果 0.220s あ、却下(笑) if の方がさすがに速いです。 あとは。。。 CString CXInt10::toString( void ) { ... // '0'を足しながらコピー for( ; pch >= m_buff; pch--, pb++ ) { *pb = ( char )*pch + '0'; } ... } やっぱりこの関数が遅いわけで、 このループを、4バイトにしましょうか。 しかし pch の初期位置は4の倍数ではないため、例外処理を 書いて、 int len = pch - m_buff + 1; int len2 = len; int i = len2 & 3; // 4の倍数になるまでコピー if( i ) { do { *pb++ = ( char )*pch-- + '0'; } while( --i ); len2 -= i; } // '0'を足しながらコピー i = len2 >> 2; if( i ) { do { ULONG c = ( *( ULONG* )(pch - 3)) + 0x30303030L; char* pb2 = pb + 3; *pb2-- = ( char )c; c >>= 8; *pb2-- = ( char )c; c >>= 8; *pb2-- = ( char )c; c >>= 8; *pb2 = ( char )c; pb += 4, pch -= 4; } while( --i ); len2 &= 3; } if( len2 ) { do { *pb++ = ( char )*pch-- + '0'; } while( --len2 ); } pb と pch の方向が逆なので、スワップしなければいけません。 うーん、馬鹿みたいに長いけど。。。 結果 0.200s 駄目ですね。100害あって1利なしです。 ま、こんなところですか。 {magclick} /*========================================================*/ さいごに /*========================================================*/ 新C言語使いにおくるチョー基本講座 第16回。 プログラムの左側に空白やタブを埋め込むことを、インデントと いいますが、 インデントは面倒ですか? 通常のC言語対応エディタならば、自動インデントを搭載して いるでしょうが、 しかし、}でインデントを下げてくれるかというと、そうで あったりなかったり、結構いい加減です。 switch のインデント方法は、ツールによってばらばらですね。 インデントを自動調整してくれるツールがあると、便利ですか? デベロッパスタジオには、デフォルトでその機能があります。 インデントのないC言語のソースを選択して、 Alt+F8 を押してみてください。 インデントを自動調整してくれます。 他人のプログラムで不可解なインデントを見たときや、 インターネットから拾ってきたソースがべったりとしているとき に、 便利です。 {magclick} /*========================================================*/ 次回予告 /*========================================================*/ 次回は7月5日(月曜日)に、第470回をお送りします。 お題は「ベクターへユーザ登録」 さて、大型計算機が大分としっかりしてきました。 ところで、 ・・・ ・・・・・・シェアウェアって、どうやって登録するのですか? お楽しみに! /*========================================================*/ 最後の決り文句 /*========================================================*/ このメールマガジンは、まぐまぐさんから発行しています。 このメールマガジンを解除したい場合は、まぐまぐさんをご利用 ください。このメルマガのまぐまぐアイディーは最後にあります。 このメールマガジンには広告が挿入されていますか? このメールマガジンの内容に文面の引用はありませんか? めーらっくすの場合はめーらっくすの利用方に従ってください。 このメールマガジンの内容の、転用、流用、宣伝、リンク、 金に走った(笑) なんて大歓迎です。 {magclick} /*========================================================*/ /*========================================================*/ 発行者 あゆしゃ ホームページ::あゆしゃの世界 http://ayusya.hp.infoseek.co.jp/ ご意見・ご感想・ご質問メール mailto:ayusya@flamenco.plala.or.jp まぐまぐ::アイディー 0000020674 まぐまぐ::登録と解除 http://www.mag2.com/m/0000020674.htm まぐまぐ::バックナンバー http://jazz.tegami.com/backnumber/frame.cgi?id=0000020674 めーらっくす::アイディー MM3E1AEE285AB4F めーらっくす::登録と解除 http://www.mailux.com/mm_dsp.php?mm_id=MM3E1AEE285AB4F めーらっくす::バックナンバー★最近のものならこちらが便利★ http://www.mailux.com/mm_bno_list.php?mm_id=MM3E1AEE285AB4F |