__int64 a, b ; // アンパック BCD
__int64 c = 0xF6F6F6F6F6F6F6F6, d = 0x0505050505050505,
e = 0x0606060606060606, f = 0x0A0A0A0A0A0A0A0A, g = 0x0F0F0F0F0F0F0F0F ;
__asm
{
movq mm0, a
movq mm1, b
movq mm4, f
paddb mm0, mm1
pcmpgtb mm4, mm0
paddq mm0, c
pand mm0, g
movq mm1, mm0
pcmpgtb mm0, d
pand mm4, mm0
pand mm4, e
psubb mm1, mm4
movq a, mm1 ; a ← result
}
a, b が、上位4ビットに3が入っている形式の場合には c の値を修正するだけでOKのはずです。
また、a - b をするには、b = f - b を計算してから加算すればOKかな…?
因みにキャリーに paddq を使っているので、SSE2 以降ですね、このコードだと。
金の計算と帳票処理なら (スコア:0)
二進化十進 (スコア:1)
良いものは良い。
なんか文句がある人がいるんでしょうか。
Re: (スコア:0)
Re: (スコア:0)
Re: (スコア:2, すばらしい洞察)
Re:二進化十進 (スコア:0)
と不思議に思った数秒後に、
FP-1100のBASICは10進演算していたのを思い出した。(だから遅かったよNE!)
・・・懐かしい思い出をありがとう。
Re:二進化十進 (スコア:1)
Z-80にもDAA命令があるのでBCD演算の実装はまあ、浮動小数の実装と比べて、
そんなに極端な差は出ないと踏んだんでしょうけど、
MSXのユーザーの大半は使ってなかったと言う…。
あと懐かしいといえばNCB(Number Crunch BASIC)てのもありましたねー。
ナンバークランチングをBASICでやろうと言うのも凄い話なんですが(^^;
とにかくBCDを実装した言語はパソコンにも割とあったと言うお話です。
ちなみにIA-32のSIMD命令にもちゃんとBCD演算を考慮した命令(四則演算)は残ってますし、
IBMメインフレームじゃなくても、実装は十分出来ると思うんですけどね。
だいたい、BCDじゃなくても、有効桁数がある程度設計で見えているなら、
64ビット整数で固定小数点演算にすれば、誤差は少ないですからJavaで何が悪い、
と言う事にもなるんでしょうね。
言語選択より、計算精度なんてもともとプログラミング時にプログラマが設計すべきものでしょ。
なので、COBOLである必要性、と言うと…書式が厳密。と言う点はあるかもしれないですが、
BCD演算に優位性がある、と言われると、うーんと考えてしまいます…。
Re: (スコア:0)
正気の沙汰ではありませんね。
ひょっとして御社ではそれでシステムの設計をなさってる…?
Re:二進化十進 (スコア:1)
極端な例を書けば、MPEGビットストリームでは各パートごとに有効ビット数がありますし、
ゲーム機の演算ハードウェアは有効ビット数が決まってます。
いや、それ以前にアセンブラ使うならレジスタのビット長をちゃんと把握して無いと計算できませんよ?
C/C++を使う場合も、自分の使っている演算長はちゃんと把握していないと固定小数点演算なんて、
アンダーフローやオーバーフローをバリバリ出してあっという間に計算が破綻するなんて割とざらですが?
FloatやDoubleだって、有効ビット数を考えて居ないと、たとえば演算で回転変換をかけたりすると、
数回転しただけで破綻しますよ。
・・・そこまで極端な事を言わなくても、たとえば、浮動小数を使っている、と言う自覚があれば、
当然誤差の含まれた計算をしている、という意識が働くわけで、数値を==で比較する、なんて、
阿呆なコードは書かないわけで、(NANや初期化直後の0とかは除いて…)、いずれにしろ、これも
「演算精度をプログラマが自覚している」って事でしょ?
むしろ上記を考えない、と言うのはプログラマとして大問題を抱えてるのではないですか?
Re: (スコア:0)
> むしろ上記を考えない、と言うのはプログラマとして大問題を抱えてるのではないですか?
当然プログラマは精度等について自覚している必要はあります。
でもそれは
> 計算精度なんてもともとプログラミング時にプログラマが設計すべきものでしょ。
とは何の関係もないことです。
普通の会社では、精度は「プログラミングよりずっと前に」「むしろプログラマ以外の人が」設計するものですが、ホント。
あなたがたは与えられた精度を満たすようなコードを書いているだけで、設計時の精度の決定には噛んだ経験はなさそう、
もしくは、愚か者ゆえにそこから何も学ばなかった(ベンジャミン・フランクリン)ようですね。
Re:二進化十進 (スコア:1)
IA32のSIMDにBCD命令って何かありましたっけ?
もちろん、整数演算でBCDを実現することは不可能ではないでしょうけど…
Re:二進化十進 (スコア:1)
Re:二進化十進 (スコア:1)
FPUおよびCPU一般命令でBCDを扱う命令がありますの間違いです。
ちなみにSIMDでBCDは全く扱えないか、と言うと、工夫次第である程度はいけそうです。
整数で実現する方法はと言うと、BCDを実現するには
ハーフキャリー(ハーフボロー)を監視すればよいのですが、
SIMDだけでやるとアンパックして、更にビットをずらしてまたアンパック後に、
比較命令でマスク生成してマスクを4ビットずらして加算してパックして更にパック。…と、面倒くさいですね。
失礼しましたです。
Re:二進化十進 (スコア:1)
加算だと
a, b が、上位4ビットに3が入っている形式の場合には c の値を修正するだけでOKのはずです。
また、a - b をするには、b = f - b を計算してから加算すればOKかな…?
因みにキャリーに paddq を使っているので、SSE2 以降ですね、このコードだと。
Re:二進化十進 (スコア:1)
>また、a - b をするには、b = f - b を計算してから加算すればOKかな…?
b = 0x090909090909090A - b が正解かな?(汗
ま、いないとは思いますが、使う場合には自己責任でちゃんと動作チェックを…(^^;;;