【问题标题】:Complex Numbers Seemingly Arising from Non-Complex Logarithms看似由非复数对数产生的复数
【发布时间】:2015-08-02 23:20:08
【问题描述】:

我有一个用 TI-BASIC 编写的简单程序,可以将基数 10 转换为基数 2

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。

我尚未对此进行彻底测试,并且在这些数字中看不到任何规律。任何帮助将不胜感激。

【问题讨论】:

    标签: debugging binary base-conversion ti-basic


    【解决方案1】:

    发生错误是因为在取整数部分之前将对数四舍五入到小数点后一位;因此,如果log(D)/log(2) 类似于8.99,您将向上而不是向下舍入E,并且将从D 中减去2^9 而不是2^8,从而导致在下一次迭代中D 变为变为负数,其对数为复数。当 D 为 511 时,让我们来看看你的代码,它的底数为 2 对数 8.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+ 上舍入错误不会累积:round(int(log(2^X-1)/log(2))返回 X-1 和 round(int(log(2^X)/log(2)) 为所有整数 X≤28 返回 X,这足够高,以至于在计算的其他部分无论如何都会丢失精度。

    要修复您的代码,只需四舍五入一次,并且只四舍五入到九个位置。我还删除了E 的不必要的双重初始化,删除了你的近括号(它仍然是合法代码!),并将Repeat(在检查条件D=0 之前总是执行一个循环)更改为While循环防止ERR:DOMAIN当输入为0时。

    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 > 213 左右都能正常工作,因为您的计算器只能在其内部表示的任何数字中存储 14 位数字。当您将结果存储到 B 中时,您会丢失数字!

    现在提供一种计算二进制表示的更复杂、优化的方法(仍然只适用于 D 13:

    Input D
    int(2fPart(D/2^cumSum(binomcdf(13,0 
    .1sum(Ans10^(cumSum(1 or Ans
    

    【讨论】:

    • 在我的 TI-83 Plus 上运行它会由于浮点舍入问题而导致错误。例如,48 将转换为“102000”而不是“110000”。关于如何解决这个问题的任何想法?
    • @JamieSanborn 如果您的 TI-84+ 系列计算器是最新的操作系统,您可以使用内置的logBASE(D,2 函数,它可以为您修复舍入错误;在您的情况下,将int(log(D)/log(2 替换为int(round(log(D)/log(2,这会将结果四舍五入到小数点后九位(太小而不会导致错误,但足够大以修复它们)。不过,这最多只能工作 2^27(仍然大于输出格式的最大精度)。
    • 啊哈!非常感谢你做的这些。我对 TI-BASIC 很陌生,你的小代码优化也有很大帮助。 :-)
    猜你喜欢
    • 2019-09-03
    • 2015-02-09
    • 2017-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-24
    • 2011-07-20
    相关资源
    最近更新 更多