来月中には出そうと思っているので、一応書いておく。
ってか、書いちゃえ。
予告ってやつですよ。
[PR] 古い通信アプリにも安心を。OverSslの継続公開についてはコメントをください。
Hobby::C++の最近のブログ記事
テキストベースで、Excelとの親和性も高いので、プログラムするには適していると思ったんだが、よくわからないことが多い。
Win32スタティックライブラリのプロジェクトウィザードでATLを選択できないのは、普通に使うとマズイことになるからと推測中。
CoInitialize*を呼ぶことができれば、多分使える。
DLLの場合、スレッドアタッチとかスレッドデタッチのタイミングでCoInitialize*/CoUninitializeすればそのスレッドではCOM利用が可能なはず。
#でも、DllMainで呼んじゃダメみたいな記述がある・・・
スレッド内にすべてを封じ込めることができれば、スタティックライブラリにしても問題ないんじゃないかという方針で進めてみようと思っている。
並行してドライバの件もなんとかしなきゃなぁ・・・
ATLって、スタティックライブラリには使えないらしい・・・
#プロジェクトウィザードで選択できましぇんので。
ATL使用部分をスタティックライブラリに内包して、メインのプロジェクトからはATLを隠ぺいしたままにしたいというのは、結果的な希望。
本質の欲求は、msxml利用部分をプロジェクトとして分離したいという、ただそれだけなのにぃ・・・
ATL使うと楽ができるというか、多分コード量も少なくて済むからバグ少なくなると思ったんだけどなぁ。
・・・でもプロジェクトのプロパティではATL利用を選択できるんで、使えそうな気がするんだよね。
どうなってんじゃろぅ。
やっちゃいけないことなんだろうか?
まだちょっと未練があって、いろいろ考えてたら、チェックサム計算を忘れていることに気付いた。
#アキバ行ったときに、TCP/IP関連の本を読んでて気づいたのが本当のところ。
だから、試しにチェックサム計算を入れたわけだ。
1の補数とか、0xFFFF == 0 とか、そんなの。
でも、やはりパケットは飛んでない様子。
結局、ダメなのかなぁ・・・
サンプルが目的に合ってないのか、やろうとしていることが間違っているのか、やり方が間違ってるのか。
多分、全部だろうな・・・
書き換え方が悪いのか、書き換える場所が悪いのか・・・
イーサフレーム書き換えることはできても、発信できていなく、ダメっぽいので、別な方法を探そうと思ったのだった。
やはり、NICに到達しちゃったあとで、送信先MACアドレスまで入ったイーサフレームも出来上がった後で何かしようと思うのは、そもそもの間違いなんだろうな。
とりあえず、またサンプルを漁るか・・・
イーサフレームを書き換えるところまではできた。
でも、まだTCPコネクションを確立できていない。
意図した書き換えもできてるし、書き換えた結果、影響は与えられているようなので、書き換える値などをもう少し見てみる予定。
超面倒・・・
ドライバはカーネルモードで動くわけで、かなりの特権が与えられる。
そんなものが、無暗にメモリを喰いまくったり、例外吐いたりしたらえらいことになるわけだということは薄々気が付いていた。
サンプルコードを見ても、alloc系関数は特定要素の生成に特化したものだったりするのは当たり前だと思ったのだが、どうも、メモリ確保には細心の注意というか、気軽にメモリ確保しちゃいけないんじゃないかと、思ったのは、今日。
一時的なメモリ領域で、固定長にできず、しかし、内容解析のために連続領域が必要・・・といった場合でも、それを確保せずに済ませる方法を考えた方が、どうやらいいらしい。
メモリ確保しないとか、変数を使わないのは、XSLTで慣れてる?
悪戦苦闘の末、読めたのだが・・・
どうやら取得できたのは、IPパケットじゃなくそれを含んだイーサパケットらしい。
まぁ、そりゃ宛先を決めるのならIPアドレスじゃなくてMACアドレスが必要だよねぇ・・・
じゃなくて、そんなところまでいかないうちに、ループバックさせないとマズイのかも。
と思いつつ、書き換えできるかを先に試してみようかと思う。
当たり障りの無い情報ならいくらでもあるんだけど、ドライバ開発するための資料となると、Webですら殆ど見つからない。
DDK(WDK)のサンプルを選んで、デバッグ表示でIPパケットダンプしようと思っただけなのに、明らかにそこに目的のIPパケットがありそうなのに、もうやり方が分からない。
ヘルプ読むと、関数とかマクロ使えとか書いてあったりするんだけど、具体的な関数名やマクロ名が分からん。
気長にコツコツやるしかないのだろう。
そのうち分かってくるといいなぁ。
XPのDDKと最新のWDKを落としてきて、英語とにらめっこしたり、サンプルコード見たりしてるんだけど、いまいちよく分かっていない。
やりたいことは分かっている。
IPパケットの書き換えだ。
直接TCP内容を書き換えるか、宛先だけをを書き換えて別プロセス(socketベースのアプリケーション)で書き換えを行わせるか、どちらかの方法でできるはずだとは考えているのだが、やはり、よくわからない。
Vista以降の場合、何とかサンプルになりそうなものを見つけはしたものの、XPでの方法がよくわからない。
やはりいきなりドライバってことに無理があるのだろうか?
最初から順番にやっていかないとダメなんだろうか?
円周率を追加したアドインの評価を完了。
あとはドキュメントだけ。
鋭意執筆中。
公開されるのは来週・・・かな。
んー、おまけにいくつか関数ぶち込んであるんで、ぜひレジストして全関数を使ってほしいのだけどなぁ。
というのはさておき、現在公開中の0.7.1にもある問題が解決できていない。
そして、アドインを登録しようとして、重大なエラーとやらが出る。
Heap blockなんとか~ってエラーだとわかり、解放時のエラーらしいというのは分かったのだが、デバッグモードでトラップするのは、非常に困難。
- Excelにあらかじめアドイン(ちゃんと登録できるやつ)を設定しておく
- デバッグビルド物件に置換
- VSデバッグモードでExcelを起動(アドインを引数にしない)
- 操作等を実施
- 例外ダイアログが出たら、デバッグでコードが出るところまで何度かボタンをクリック
これで、何とか原因を突き止めることができる。
今回の問題は、デバッグ実行時の引数にアドインを指定してると呼び出されない関数にあったので、はじめはわけが分からなかった。
#現在リリースされているものとは違うコードです。
こういう手法に気付くまでが大変だけど、コードや呼び出し履歴を掴めれば、どこの何が原因かを判別するのが容易になる。
ま、気にする人はいないだろうけど、メモがてら。
- 絶対値・・・実装。
- 円周率・・・実装。
- SQRTPI相当・・・実装延期。
- 桁指定・・・実装延期。
- SUM系・・・実装延期。
- 数値化・・・追加実装。
ま、こんなところか。
円周率は出せているし、絶対値も現状用意済みの内部関数を呼ぶだけ。
あとは数値化だが、これも何とかなったっぽいので、これで、出せる・・・と思うのだが、デバッグモードで実行すると、例外がボロボロ出るところがあるので、原因を調べてからにしたい。
数値化はとても便利かも知れない。
#現状、Excelには255文字以上の数値文字列を数値化する関数が無い。
64bit版もできるんだけど、これは要望か何かがあるなら考えるけど、メジャーバージョンアップまで非公開の予定。
と、声に出して言いたい。
パイと言っても円周率(π)ですが。
いや~、スタティックライブラリのリソースからロードするのって、結構難しいですね。
あと、ちょっとリソースファイルの編集について、インクルードを処理するのは、リソースビューで開いて、「リソースファイルのインクルード」でやると簡単だったことをメモしておく。
で、πですが、こんな感じ。
しかし、もし、仕様ならば、仕方ないし、そうじゃなくても、現状そうならばそうで対処するしかない。
#回避策があるのならば、それに頼る。
##回避策が無いのに、不具合を仕様と言っちゃう(再起動したところで、再現を繰り返すだけ)のは愚かなだけだが。
とりあえず、関数の説明は同梱のPDFにお任せしちゃうことで、無しにすることは不可能ではないので、それで対応してみる。
さて、円周率3万桁、ちゃんと出るかはこれから確認。
例のXLLSDKをやっと取り込んだんだけど、やはり引数なしでうまくいかない。
サンプルだと引数なし関数の登録がうまくいくのかと思っていたのだけれど、試しに関数の説明まで出そうとしたところ、引数ありになってしまうことが分かった。
関数の説明を端折ると、引数なしとして登録できる。
これは誰のせいなのか、全く分からないのだけれど、Excelのせい?なのか・・・よくわからん。
とりあえず、Excel2003でも2010でも挙動が同じだったこと、VS2008でもVS2010でも結果は変わらなかったことをメモとして残しておく。
いやはや、さて、困ったぞ。
本読んでもこのあたり書いてないんだよなぁ・・・
あと、文字列(関数の説明以降)の最後1文字が切れるのも俺のせいじゃないらしい。
そういえば、引数なし関数がうまく登録できないとき、関数の引数んとこに空白1文字入ってるっぽいんだよね。
余分な1文字と無くなる1文字で辻褄は合ってるのか・・・?
んー、英語版Excelで試してみるか・・・
ただし、バッチファイルではなく、ファイルコピーで。
ビルド前イベントに設定したコマンドは以下(全ての設定で共通)。
copy "$(ProjectDir)StdDef\$(ConfigurationName)_$(PlatformName).h" "$(ProjectDir)StdDef.h"
StdDefフォルダに「構成名_プラットホーム名.h」でStdDef.hの内容をそれぞれの設定用に記述しておくと、ビルド前にコピーしてくれて、それでOK。
あとは、リソースファイル(.rc2, resource.h)とかstdafx.hとかで#include "stddef.h"してあげればOK。
一つ注意があるとすれば、VC++はデバッグ構成時に_DEBUGを強制定義してくるらしいこと。
よって、デバッグ構成のときは、
#ifndef _DEBUG
#define _DEBUG
#endif
のように定義しておく。
これで、二重定義警告を抑制できる。
#そして、もし定義されていない場合でも、定義される安心。
デバッグモードコンパイルなのか、リリースモードコンパイルなのか、判断して、バージョン情報リソースに任意の文字列として埋め込みたいとか思うと、VC++の場合、リソースコンパイラのプリプロセッサ定義が独立しているので、C/C++コンパイラのそれと2か所に設定せねばならず、面倒なのだ。
で、ちょっと思いついたのでメモ。
- プリプロセッサの定義で構成ごとに変わるものを抜き出しておく。
- バッチファイルなどで、引数指定すれば、特定のファイル(.h)に#define列として書き出せるようにしておく。
- ビルド前イベントに登録し、引数を一意にする。
- リソースやC/C++コードで書き出されたファイルを#includeする。
こうすることで、設定は1か所になるはずだが、果たして・・・
#後日試してみる。
超長文字列のリソース埋め込みができそうなので、Excelのアドインで円周率を3万桁ほど返してみようとしたところ、とんでもないところで躓くことになった。
#悩みまくりのお手上げ。
なんと、引数なし関数の登録ができないのだ。
なぜ、できないのかは、よくわかっていない。
SDKのサンプルではいとも簡単に登録できているし、引数ありなら問題ないのに、引数なしになった途端に破綻する。
#途端破綻、ドタンバタン。
ま、いい機会だから、気になってたところを直しつつ、VS2010に移行して、メモリ使用効率もあげちゃおうかと考え中。
#計算部分には手を入れないつもりなので、高速化はできないと思う。
かなり手間だけど。
同時に64bit対応化も。
要は.rc2ファイルへ移動させればよいのだけれど、プロジェクト雛形によってはrcもrc2も無い場合があるので、メモ。
まず、プロジェクトにリソースファイル(.rc)を追加して、バージョン情報リソースを作成する。
これはVC++の統合環境から実行できる。
次に、.rc2の追加だが、これは面倒。
単に.rc2ファイルを追加してもダメなので、.rcファイルの修正が必要になる。
.rcファイルをメモ帳か、VC++のテキストエディタで開いて、
3 TEXTINCLUDE
の箇所と、
// Generated from the TEXTINCLUDE 3 resource.
の箇所に呪文を追加する。
ただ、呪文は結構難しいので、別途作成したMFCプロジェクトの.rcファイルの記述を参考に記述する。
#もしかするともっと簡単な方法があるかも知れない。
そして、VS_VERSION_INFO VERSIONINFOからの一連のバージョン情報を.rcから.rc2へ移動させる。
移動すると、どんないいことがあるかというと、たとえば、リソースエディタでの変更保存時でも削った不要な情報の再作成が行われないとか、プリプロセッサによる条件分岐を設定しても消されないとか、なんかこんなこともできたりするらしい。
リソースエディタが使えなくなるけど、ある程度プロジェクトが固まったらそんなに編集するものではないので、移動させて勝手に変更されなくするのもアリだと思う。
昨日の記事で、発見したXLLSDKのヘルプドキュメントをちらっと見たところ、非同期関数を定義できるとか。
長時間掛処理でExcel無応答になることが、これで防げるのかどうか、どちらにしろ、Excel2010の新機能だと思われる。
長時間処理といえば、HyperLong系の処理なのだが、これ、非同期にしたら、実行時間は変わらなくても、処理的に軽くなるかも知れない。
やってみる価値はありそうだ。
過去記事の誤り。
「署名があるとか無いとか、そんなことはどうだっていいんです」という結論。
やってみることは大事だね。
ただ、まだ、「動いた」というレベルだけれども。
とりあえず、Excel4系関数を排除して、Excel12系関数(SDKだと、_WIN64定義時に呼べないようになってるのを解除)のみにして、x64ターゲットでコンパイル。
すると、登録もできるし、関数も呼べる。
手放しで喜ぶのは構造体のアラインメントを詳しく確認してからなのだが、とりあえず、Excel2007と同程度のことはできそう。
それ以上の何かを期待できるかも知れないのだが、まずは、そこから。
・・・と、少し満足してたら、こんなものが!!
出てるなら出てるって教えておくれよ!!!<いや、無理。
仕方ない、中身調べてみるか・・・
継承すれば、親クラスのprotectedメンバにもアクセスし放題とばかり思っていた。
この十年余り。
俺もまだまだだな。
こんなC++コードを書くと、「A& GetA(A& org)中のorg.A::GetA()呼び出しって、protectedだからアクセスできないよ~」というコンパイルエラーが出る。
A& GetA(B& org)の方は大丈夫。
なんとなーく、Aのprotectedメンバにサクサクアクセス出来ちゃいそうに思っていたので、自己修正、覚え直し。
C#でも試したけど、同様。
Office2010の64bit版をインストールしたので、64bit版ExcelでAddin for Excel 95-2007の動作を確認してみたところ、動かない。
動かないというか、アドインの追加で躓く。
原因は、
- 32bitだから
- 署名がないから
- その他
など考えられる。
Addin for Excel 95-2007 Basic EditionのVer0.7.1を公開した。
せっかくコンピュータ使ってんだから、有効桁なんてケチなこと言わず、どーんと数百~数万桁使っちゃえ的に加減乗除+開根+比較までできるってことは、100円電卓レベルの操作を多桁で実現できちゃったってことだ。
開根には時間掛るけど、100円電卓では得られない精度。
互換関数使えば互換性と処理速度と精度のいいとこ取り。
是非使ってみて欲しい。
HyperLong系の加減乗除、開根、大小比較まで出来るようになっている0.7.1もまだ公開されてませんが、次回(0.7.2)の予告。
絶対値取得関数。
開根関数には必須。
実は、文字列として、たとえ負の数だろうが、- を先頭に付けるだけで、符号反転できたりする仕様なので、条件判定して、- を文字列連結しちゃえばいいんだけど、それだと32767文字超えちゃう可能性があるので、関数として用意しておいたほうがいい。
円周率定数関数。
定数なので、計算処理無しで返したいところ。
これまで、「そんなに長く円周率算出して実際使うのは10ケタも無いじゃん」って言われ続けてきた円周率をこれでもかというくらいに長く利用できるようになったので、なが~く出せるように。
ついでにSQRTPI関数っぽいものも。
あとは提供方法考え中なのが、返却の文字列長指定。
あると、結構便利な予感。
他には、SUM系の関数をと考えてるんだけど、今のところ未定。
ま、こんなところかな。
徐々に追加すれば良い。
Excelの多桁開根関数を追加したやつ、登録しました。
Addin for Excel 95-2007 Basic Edition
多分、来週には公開されるんじゃないかな。
サポートはこちら。
今回のバージョンは、0.7.1になりまする。
是非、ご利用くださいな。
多桁数比較関数として、HLCOMPを用意してみたものの、Excel95のIF関数内で条件に使うと、なぜか#NUM!エラーになる。
HLCOMPを別セルで計算して、その値を条件に使えば問題ないし、IF関数の真偽値としてエラーを返す可能性の無いリテラルを指定すれば、これもエラーにならない。
HLCOMPの仕様は、引数2つをとり、>なら1、=なら0、<なら-1を返すというもの。
確かに、#NUM!エラーを返すパスもあるんだけど・・・
同様に、#NUM!を返す可能性のあるSQRT関数を条件に使う場合、そんな問題発生しないんだよなぁ。
で、Excel2003だと、再現しない。
#95~2003のどのバージョンまで再現するかは未確認(やらなきゃまずいかなぁ)。
原因はExcel95にあると思うのだけど・・・
ExcelでSQRTに負数を与えると、#NUM!エラーとなるわけだが、多桁の現実装は絶対値に対して平方根を計算している。
互換関数もよさげにできたっぽい評価結果が得られてるんだけど、そろそろ公開をと考えているのだが、さて。
今回比較関数を用意したので、負数を事前に排除することもできるわけだし、#NUM!エラーを返すようにするかな。
追加で絶対値を返す関数を用意する意味も出てくるし。
Excelで多桁計算。
現在公開されているのは、四則演算まで。
開根実装の目途はついた(と思っている)。
遅いけど。
遅さをカバーする意味も含めて、全Excelで同じ桁数を返す互換関数を用意しようかと思っている。
255文字分で表現可能な値を返すってやつ。
返却を短くできる分、処理が軽くなるので、開根の遅さをある程度カバーできる。
入力(引数)文字数はExcelバージョン依存で出力(解)文字数は互換となる予定。
乗算の打ち切り方について、まだよくわかってないので、入力依存。
除算・開根の打ち切りはできる。
加算・減算の打ち切りはしない。
で、提供予定としておく。
ついでに、比較演算関数も加えたいなぁと考えている。
そして、あともう2つほど関数を考えているのだけど・・・
高速化ってのは、処理を軽量化する方向でやるのと、そうでない場合があると俺は思う。
前者はたとえば、条件分岐を減らしたり、計算回数を減らしたり、より簡易なコードにすることが多いと思う。
#Simple is Bestってやつ。
今回(今日)の大幅な高速化は後者。
1位にいくつか数を加えた場合の桁上がりを処理するのは、1位値が10を超える場合のみでいいという、いわゆる打ち切り条件を加えた。
#条件によっては効果が無いけれど、今回はやる前から処理分岐率50%で、その分の処理を打ち切れるという、かなの効果を見込んでいた。
桁上がり処理は、全桁を確実にループするため、条件によってやらなくていいというのは、メリットだろうと思ったわけだ。
おまけに、その処理は何度も通るため、結果、条件判断に掛るコストよりも大幅な処理速度改善につながったわけだ。
にしても、びっくりするのは、これで限界と思ってた60秒から30秒台まで高速化できたことよりも、処理のほぼ半分も無駄なことやってたこと。
さすがに俺もこれには笑うしかない。
#その後、もう少し手を入れて、30秒切るところまできました。
環境は、Core2Duo L7500(1.6GHz)のまま。
開根時に多用してる減算をどうにかしたら速くなるんじゃないかということで、加算減算を見直し。
今までは、加算では各桁加算ループと桁上がり処理ループに分けていたんだけど、ループを1回で済ませられるように変更。
減算も、桁下ろしループ、各桁減算ループ、桁上がりループの3ループを1ループ化。
これだけで、60秒を切りそうな勢いで高速化できた。
他にもいろいろと手を入れているものの、減算の変更は一番効いたと思う。
もう少し見直して、余裕で1分切りを目指したいと思う。
#でも、実用とは言い難いので、別の策を考え中。
開根筆算では2桁ずつ下ろしてくる処理がある。
これを省略してみたところ、少し速くなって2や3の開根で80秒を切れるようになった。
これが限界だと思っても、諦めなければ、その先がある。
でも、多分、今のままで1分切るのは難しい。

※A3には =HLMLT(A2,A2) で検算。
多桁開根確認中、数バイトのnewでヒープ破壊の例外発生。
何が原因かは目下不明。
Free Heap block xxxxxxxx modified at yyyyyyyy after it was freed
と言われるので、yyyyyyyyアドレスを見ると、確かに周りと違う値。
参照変数は、別スコープに移動したし・・・飛び地を不用意に書き換える処理は入っていないはず。
OS再起動して再現するようなら調査続行か。
メモリ使用量を減らしたり、演算回数を減らしたりして、処理速度アップを狙ってはいるのだけれど、どうも、方法にも限界はあるし、そもそものクラスのメモリ使用方法自体にもボトルネックがあって、どうにも速くならん。
2の開根で32767桁(文字(整数部や小数点等を含む))、二乗誤差は最小位+1なのはいままで同様。
二乗検算まで含めると結果表示まで、約2分。
そう、何とか2分を切るくらいまでは高速化(とは言えないが)できた。
開根のみであれば、なんとか90秒を切れるようにはなった。
#非常にうれしいのだが、全く実用的ではない。
しかし、これ以上高速化しても、恐らく1分の壁すら到達できないだろう。
なんにしても、クラスの基本部分を弄るしかないだろうと思っている。
開根くらいでもたついていては、開立や三角関数なんてどんなに時間が掛ることか知れたもんじゃない。
公開されたようです。
Addin for Excel 95-2007 Basic Edition ダウンロードページ
Addin for Excel 95-2007 Free Edition ダウンロードページ
不具合修正されてますので、是非。
ずっと考えていたけど、無いんですよね、必要な場面って。
昨日からの続き。
そして、構造体にコンストラクタを用意したところ、構造体を取り込んだ共用体でコンパイルエラーが発生する罠。
曰く、「共用体メンバに既定のコンストラクタを持たせることはできません」だそうな。
じゃぁ、既存構造体から新たに継承したクラスを作って・・・とかやると大手術になってしまうので、仕方ないからそれは次期バージョンにて考慮。
今回は、newでサーチしてnewや変数宣言など、構造体メモリを確保している箇所で片っ端から初期化してやろうと思う次第。
#必要な個所だけ。
他に、実はnewしているのは決まってExcelに返すデータをエクスポートする箇所なので、それらを一か所に集約してやろうかと。
これで今回の原因は撲滅できるはず。
100%確実ではないけれども、再現させる方法だけは見つけたので。
Windows 7を起動して、評価に使用したExcel95ブックをExcel2007で開くだけ。
すると、再計算50%を過ぎたところあたりでExcelがエラー(動作を停止)を起こす。
ここら辺が微妙なんだけど、50%のときもあれば、そうでない場合もあり。
2回目には起こらないので、都度OS再起動が必要。
ところが、通常、プロセスの異常時には、「デバッグしますか?」のダイアログが出るのだけれど、このExcel2007は自動修復するのか、デバッガでアタッチするとプロセスが終了してしまう。
困ったことナリ。
デバッグモードでは再現したことがないので、あたりをつけようにも・・・
とりあえず全エクスポート関数の大部分をtry~catchで囲んでみたのだけれども、状況は好転せず。
なんだか変。
Windows7やVistaで動作確認しようと、アドインを設定して、気を良くしてHLDIV(10,3)とかやるとExcel停止・・・
なんでやねん!
デバッグしようとしても痕跡なし。
じゃぁとVS2008からデバッグ実行すると、全く落ちず。
そうこうしてるうちにExcel停止が再現しなくなる。
なんだこりゃ?
重要。
でも、検算するのがとても大変なのは多桁演算の宿命。
だから、大体正しければいい、というものでもない。
除算の評価結果を見ていて、変なことに気付いた。
検算をするとどうもおかしい。
筆算してみても、自分が間違えてる可能性もある。
Windows付属の電卓はかなりの桁数計算できるが、それと比較すると、やはりどうも多桁計算側がおかしいようだ。
使用メモリ量と演算回数を削減したんだけど、Excel95落ちるようになっちゃいました・・・
多分、どこかで例外発生しているってことなんだろうけど。
おっかしいなぁ・・・って、よく見たら凡ミス。
直したら動くようにはなったけど、やはり重い。
#加算・減算だけでなく、内部で加算処理をしている乗算も重い場合がある。
リソース絡みだと思いたい。
Excel95のリソース制約は一番厳しいので、Excel95で動けばExcel2003でも動く。
#Excel2007からは別物だけど。
なんか、すごく重い。
今のところ原因不明。
Excel95で桁数多い場合に発生中。
Excel2003では発生しないようだした。
Excel95では同じ計算でも発生するときと、しないときがあるようだ。
数としてはあってもいいんだけど、-0が返るパターンがあったので、符号補正を入れて修正。
別に、1文字2文字で困る文字数じゃないから放置してもいいんだけど、0と-0が違うかっていうと十進数演算の中では同じなので、だったら符号不要ということで。
多桁計算にも一応、四捨五入丸め処理を入れている。
というのは既出だが、Excelに文字数制限があるため。
つまり、表現上、数に制限が生まれるわけで、普通の有効桁と同じ扱いと思ってくれればいい。
除算した場合、循環小数なんかはその限界まで延びるのだけれど、そこで四捨五入が必要になる。
掛け算でも桁が多ければ丸める必要がある。
多分、浮動小数点絡みだと思うんだけど、微妙に異なるらしい。
それも、Excelのバージョンによって、微妙さも違うときた。
これにより、計算結果を評価するのがとても面倒なんですが・・・
どうやって評価しようかと、そんなところで躓く。
因みに、やってびっくりしたのが、=1.5*1.3-1.95って計算、Excel95でやると、2.22E-16になるんだぜ・・・。
どうしてやろうか。
多桁乗算を使って、=VALUE(HLMLT(1.5,1.3))-1.95を計算すると、Excel95でも、0が返るんだけどな。
C/C++(非.NET)でHTTPSクライアントをつくるとき、OpenSSL使わなきゃできないと思い込んでいたんだけど、ことWindowsに関して言えば、OpenSSLをインストールしなくても、IEとかで普通にHTTPSアクセス出来てるので、単なる思い込みだった。
マルチプラットホーム対応するならば別だけど、Windows専用ならば、MSXMLを使えばできるっぽい。
Windows2000以降になるようだが、IServerXMLHTTPRequestなオブジェクトを使うと、HTTPSコンテンツを取得できたので、これは素敵過ぎる。
MSXMLを使う利点は、MSXMLに不具合があっても、WindowsUpdate(MicrosoftUpdate)で対応できる点。
#つまり、MSXMLを利用するアプリケーション開発側の対応は不要ということ。
一応、オレオレエンタープライズなオレオレワイルド証明書を使ってるこのブログサイト(https://blog.fne.jp)のコンテンツも取得できたので、こいつは使える。
#エンタープライズルート証明書のインストールは必要です(多分)。
乗算と除算、ずっと考えていた方法でできそうだったので、気合い入れて実装しちゃいました。
まだ評価していないけれど。
加算・減算・乗算・除算の4関数を軽く動作確認。
処理速度にはちょっと満足できないけれど、処理結果にはほぼ満足。
小数点以下数万桁の数に意味はあるのかと問われれば、あると答える根拠を持ち合わせているわけでは無い。
けれど、逆に本当に無視していい数なんてあってよいものかと考えたら、小数点以下数万桁でも無視するのは忍びない。
だから、できるだけ多くの桁を利用したい、そのための多桁計算関数。
そして、リソースを喰い尽くす罠。
さて、どのEditionに組み込んで、バージョンをいくつにするか、決めなきゃな。
とりあえず、今回はBasicEdition(有料版)かなぁ。
因みに、まだまだ追加予定の関数はありますよ。
E(10のn乗)も処理できるようになったので、なかなか使えそうなものになった。
A2セルには「=-1.23456789012345E-21+123」と、普通に計算してみた。
当たり前だが、有効桁(Excelの場合15桁らしい)丸めで無視される大きさなので、A2セルの結果は123。
A1セルのHLADD(自作関数)ではちゃんと計算できている。
HLADDなら、小数点や符号を含みながらも、3万桁超(Excel2003以前は255桁)まで対応している。
因みに、E±9999まで入力可能にしたので、本来は文字列で指定した方がよいのだが。
残念なのは、まだ加算と減算しかできないってところか。
Excel関数にすると気になっちゃうのがEの処理。
文字列引数を受け取る関数にしたんだけど、ある程度の桁数の数値を引数に指定すると、E付きの文字列になっちゃう。
できればEを有効に読み取ってあげたいところ。
もうちょっと時間を掛けよう。
ので、少しうれしい。
何でもそうだけど、実際にやろうとすると、意外に手間取るよね~。
一応、走査回数は標準2回(最悪n^2オーダーになる条件が含まれるけど)でパースできるようにした。
#本当は1回でやるべき。
符号は数値前のものだけ。
でも複数連続符号も認識できるように。
数値中のカンマや空白の読み飛ばし機能とか、数値前後の文字列を無視する機能とか、そういうのも実装。
よくある話。
VC++のWin32(非MFC)のウィンドウアプリケーションプロジェクトのひな型では、クラス化されてないコードでだらだら書かれているので、クラス化したいなぁと思うわけだ。
思うことは自由なんだけど、WndProcコールバックがクラスメンバだからということで、いろいろ困難が付きまとう。
http://fne.cocolog-nifty.com/blog/2009/10/post-7c67.html
で書いたコード、確かにコマンドラインコンパイルでは問題なく動いたのに、プロジェクトに組み込んだら、#defineの中身を解釈してくれないばかりか、コンパイルエラー出まくる。
仕方ないので、ベタ書きした。
忘れないように。
constメンバ関数のconst意味は、そのconstメンバ関数を実行する際に所有するオブジェクトの内容を変更しないという意味だが、それ故、constオブジェクトが実行できるのはconstメンバ関数に限られるということ。
つまり、
void Hoge::Func(const Hoge &obj)
{
if( obj.IsOK() ) // call Hoge::IsOK()
{
Hoge.m = obj.m;
}
}
のときの、Hoge::IsOK()はconstで定義されていなければならないということ。
この場合、bool Hoge::IsOK() const;のような定義が必要。
#たとえ、Hoge::IsOK()の中で変更をして無いとしても、constの省略はコンパイラエラーを招く。
うっかり忘れて多量のエラーを吐かれると、イヤなのでメモ。