【问题标题】:How to convert Decimal (Base 10) to Fractional bases (i.e. Base 3/2) in Javascript如何在 Javascript 中将小数(以 10 为底)转换为小数底(即以 3/2 为底)
【发布时间】:2020-12-29 11:12:30
【问题描述】:

我发现很多资源都在谈论基数转换算法和使用内置的 Javascript 函数将十进制转换为二进制或十六进制,但是我找不到任何关于如何转换为任何小数基数的资源,例如 base 3/2 . sequinary 数字系统很有趣,我希望能够使用它,但是我找不到任何方法可以从 Decimal 转换为它。

红片系统如下:1、2、20、21、22、210、211、212、2100、2101等

我找不到任何可靠的方法来转换它。这是我到目前为止的代码:

function decimalToBase(number, base) {
            let digitArray = [];
            let quotient;
            let remainder;

            for (let i = 0; i < 16; i++) {
                quotient = Math.floor(number / base);
                remainder = number % base;
                digitArray.unshift(remainder);
                number = quotient;

                if (quotient == 0){
                    break;
                }
            }
            console.log(digitArray)
        }

它适用于 10 以下的整个基数,但如果我输入像 3/2 这样的小数基数,那么我会得到带小数的结果:

[1, 0.5, 1, 0] // When It should be: [2, 1, 0]

任何帮助将不胜感激。

【问题讨论】:

  • 一方面,您不能将% 用于非整数基数。
  • @ChrisG 我会用什么代替?
  • @ChrisG 我不明白为什么这会是个问题
  • 嗯...通常在n的数字基础系统中,数字范围从0...n-1。例如,基数4 有数字0, 1, 2, &amp; 3。似乎使用建议的基数 3 / 2 的 sesquinary 系统,数字 2 是允许的?!基数3 / 2 是允许数字0, 1, &amp; 2 的逻辑是什么?
  • @JonTrent 这实际上是一个常见的误解。您会被引导相信基数的值是符号的数量,但这实际上只是一个巧合。否则分数基将是不可能的,但它们在数学上与整数基一样可靠。据我所知,符号的数量是分子的值(在整数基数中,分子只是基数的值),因为不可能有 3/2 的数字。

标签: javascript decimal counting base base-conversion


【解决方案1】:

对于3/2 的具体情况,James Propp 的this article 公开了几种方法,其中一种方法由 Simon Norton 在尾注中描述:

这是基于这样一个事实,当 n 写为 3k + r,其中余数 r 为 0、1 或 2 时,n 的 sequinary 表示等于 2k 的 sesquinary 表示,加上数字 r在末尾。这为我们提供了一种快速的方法,可以通过反复除以三、四舍五入和加倍的过程,从右到左编写 n 的 sesquinary 表示。

go read the full article

他们还提供了一些 Mathematica 代码来运行它。

S[n_] := If[n < 3, {n}, Append[S[2 Floor[n/3]], Mod[n, 3]]]

我真的不知道 Mathematica,所以我不能真正在 js 中一对一地重写它,但是如果我正确理解算法,那将是这样的:

const decimalToSesquinary = (n) => {
  const res = [];
  while (n) {
    const k = Math.floor(n / 3);
    res.push(n % 3);
    n = k * 2;
  }
  return res.reverse().join("");
};

console.log(decimalToSesquinary(6)) // expected "210"
console.log(decimalToSesquinary(7)) // expected "211"
console.log(decimalToSesquinary(8)) // expected "212"
console.log(decimalToSesquinary(100)) // expected "212001201"

【讨论】:

    【解决方案2】:

    使用以下资源...

    ...建议的解决方案是...

    <html><body>
    BaseHi: <input id='hi' value='3' /><br>
    BaseLo: <input id='lo' value='2' /><br>
    Value:  <input id='val' value='6' /><br>
    <button onclick='go()'>Go!</button><br>
    <br>
    <br>
    Result: <span id='result'></span>
    <br><br>
    Check: <span id='check'></span>
    
    <script>
    
    function decimalToBase( number, baseNum, baseDen ) {
    
      let digitArray = []
      digitArray[ 0 ] = number;
      let i = 0;
      
      while ( digitArray[ i ] && baseDen < digitArray[ i ] ) {
        let qi = Math.trunc( digitArray[ i ] / baseNum );
        let ri = digitArray[ i ] - qi * baseNum;
        digitArray[ i ] = ri;
        digitArray[ i + 1 ] = ( digitArray[ i + 1 ] || 0 ) + qi * baseDen;
        i++;
      }
      
      digitArray.reverse();
      return digitArray;
      
    }
    
    function go() {
      let baseHi = parseInt( document.getElementById( 'hi' ).value );
      let baseLo = parseInt( document.getElementById( 'lo' ).value );
      let value = parseInt( document.getElementById( 'val' ).value );
      if ( baseHi <= baseLo ) {
        document.getElementById( 'result' ).innerHTML = 'Error - BaseHi must be greater than BaseLo';
        return;
      }
      let result = decimalToBase( value, baseHi, baseLo );
      document.getElementById( 'result' ).innerHTML = `${value}<sub>10</sub> = ${result.join( '.' )}<sub>${baseHi}/${baseLo}</sub>`;
      
      let check = '';
      let total = 0;
      for ( let i = result.length - 1, bd = 1; 0 <= i ; i--, bd = bd * baseHi / baseLo ) {
        total += bd * result[ i ];
        check = `${result[i]}*(${baseHi}/${baseLo})<sup>${result.length - i - 1}</sup>` + ( check ? ' + ' : '' ) + check;
      }
      document.getElementById( 'check' ).innerHTML = `${check} = ${total}<sub>10</sub>`;
    }
    </script>
    </body></html>

    编辑: 调整后的答案以允许轻松测试各种基数和值,包括交叉检查以将新基值反向计算回基数 10。令我惊讶的是,该算法似乎在 BaseLo

    享受吧!

    【讨论】:

      猜你喜欢
      • 2022-12-07
      • 1970-01-01
      • 1970-01-01
      • 2010-10-14
      • 1970-01-01
      • 1970-01-01
      • 2020-10-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多