shell:自定义数基算术

shell: arithmetic with custom number bases

我必须编写一个命令行,在两个不同的自定义基础中输入两个数字,并在第三个基础中输出。

自定义基础,我的意思是我有这样的东西:

所以从那开始我猜 bc 没有帮助,对吧?

是否有这样的命令,或者我应该编写一些自定义脚本吗?你能给我一些线索吗?我完全迷路了。

编辑:练习的确切说明是:

Write a command line that takes numbers from variables FT_NBR1, in ’"?! base, and FT_NBR2, in mrdoc base, and displays the sum of both in gtaio luSnemf base.

以具有以下值的方式:

FT_NBR1=\'?"\"'\
FT_NBR2=rcrdmddd

我会得到以下输出:

Salut

如何将字符串 789 转换为数字?

嗯,789等于

7×102+8×101+9×100

但是我们正在编写一个程序,我们希望利用循环。

( ( 7 ) × 10 + 8 ) × 10 + 9

更好的是,

( ( ( 0 ) × 10 + 7 ) × 10 + 8 ) × 10 + 9

我们不以数字 789 开头,而是以它们的字符串表示形式开头。

(
   (
      (
         0
      ) × 10 + [ offset of "7" in "0123456789" ]
   ) × 10 + [ offset of "8" in "0123456789" ]
) × 10 + [ offset of "9" in "0123456789" ]

最后,让我们消除对基数 10 的最后一点依赖。

(
   (
      (
         0
      ) × [ number of symbols in "0123456789" ] + [ offset of "7" in "0123456789" ]
   ) × [ number of symbols in "0123456789" ] + [ offset of "8" in "0123456789" ]
) × [ number of symbols in "0123456789" ] + [ offset of "9" in "0123456789" ]

所以代码看起来像这样:

  1. n 设置为 0。
  2. 设置base为基数中的符号数。
  3. 对于每个数字,
    1. 设置nnbase相乘的结果。
    2. 获取组成基数的符号数组中数字的偏移量。
    3. 设置nn和偏移量相加的结果。

示例 Perl 实现:

my @syms = split //, "01234567890";
my %sym_offset = map { $syms[$_] => $_ } 0 .. $#syms; 

my $s = "...";

my $n = 0;
for my $sym ( split //, $s ) {
   my $offset = $sym_offset{ $sym };
   $n = $n * @syms + $offset;
}

$s = $syms[ 0 ] if !length( $s );

say $n;

这个过程的反面可以取一个数字并将其转换为基数。不是重复乘法,而是重复除法,使用余数作为构成基数的符号列表的索引。

  1. 设置base为基数中的符号数。
  2. s 设置为空字符串。
  3. 虽然 n 大于零,
    1. n 除以 base 的余数。
    2. 获取在偏移量等于余数的符号。
    3. 将符号添加到 s
    4. 设置nn减去余数的结果。
    5. n设为n除以base的结果。
  4. 如果s是一个空字符串,
    1. s 设置为第一个符号。

示例 Perl 实现:

my @syms = split //, "01234567890";
my %sym_offset = map { $syms[$_] => $_ } 0 .. $#syms; 

my $n = ...;

my $s = "";
while ( $n ) {
   my $offset = $n % @syms;
   $s = $syms[ $offset ] . $s;
   $n = ( $n - $offset ) / @syms;
}

say $n;

好吧,我还不够聪明。我可以只用 trbc

我使用 tr 将奇怪的“基数”和 bc 与正常数字相互转换。

这是我所做的:

#!/bin/sh
NUM1=$(echo "$FT_NBR1" | tr \'\\\"\?\! '01234')
NUM2=$(echo "$FT_NBR2" | tr mrdoc '01234')
RES=$(echo "obase=13; ibase=5; $NUM1 + $NUM2" | bc)

echo $RES | tr '0123456789abc' 'gtaio luSnemf'