2

基数 10 から基数 2 に変換する TI-BASIC で書かれた簡単なプログラムがあります。

0->B
1->E
Input "DEC:",D
Repeat D=0
int(round(log(D)/log(2),1))->E
round(E)->E
B+10^E->B
D-2^E->D
End
Disp B

これにより、「ERR: DATA TYPE」というエラーが返されることがあります。確認したところ、変数 D が複素数になる場合があるためです。これがどのように起こるかわかりません。

これは、5891570 のように一見乱数で発生します。この数値では発生しますが、5891590 のようなそれに近い数値では発生しません。これは奇妙なことです。1e30 でも発生しますが、1e25 では発生しません。別の例は、1111111111111111 であり、1111111111111120 ではありません。

私はこれを徹底的にテストしておらず、これらの数値にパターンは見られません。どんな助けでも大歓迎です。

4

1 に答える 1

2

整数部分を取得する前に、対数を小数点以下 1 桁に四捨五入するため、エラーが発生します。したがって、log(D)/log(2)が のようなものである場合、切り捨てではなく8.99切り上げ、の代わりに D から減算されるため、次の反復で負になり、その対数が複素数になります。D がで、底 2 の対数が の場合のコードを見てみましょう。E2^92^8D5118.9971

Repeat D=0          ;Executes first iteration without checking whether D=0
log(D)/log(2        ;8.9971
round(Ans,1         ;9.0
int(Ans             ;9.0
round(Ans)->E       ;E = 9.0
B+10^E->B           ;B = 1 000 000 000
D-2^E->D            ;D = 511-512 = -1
End                 ;loops again, since D≠0
---next iteration:----
log(D               ;log(-1) = 1.364i; throws ERR:NONREAL ANS in Real mode

round(私の TI-84+ では丸め誤差が累積しないため、対数を小数点以下 9 桁 ("digits" 引数がない場合の既定値は 9 桁) より厳密に丸めることは完全に不要です: round(int(log(2^X-1)/log(2))X-1 をround(int(log(2^X)/log(2))返し、すべてに対して X を返します。整数 X≤28。これは、計算の他の部分で精度が失われるほど十分に高い値です。

コードを修正するには、丸めを 1 回だけ行い、9 桁にするだけです。また、 の不要な二重初期化をE削除し、閉じ括弧を削除し (これはまだ正当なコードです!)、Repeat(条件をチェックする前に常に 1 つのループを実行するD=0) をループに変更して、入力が 0 の場合Whileを防止しました。ERR:DOMAIN

0->B
Input "DEC:",D
While D
int(round(log(D)/log(2->E
B+10^E->B
D-2^E->D
End
B            ;on the last line, so it prints implicitly

あなたのコードまたは私の修正が D > 2 13程度で正しく機能するとは思わないでください。電卓は、数値の内部表現に 14 桁しか格納できないためです。結果を B に格納している間、数字が失われます。

次に、バイナリ表現を計算するための、よりトリッキーで最適化された方法について説明します (まだ D < 2 13でのみ機能します。

Input D
int(2fPart(D/2^cumSum(binomcdf(13,0 
.1sum(Ans10^(cumSum(1 or Ans
于 2015-08-03T00:58:18.600 に答える