7

たぶん私は数学があまり得意ではありませんが、Microsoft Excel / OpenOffice Calcと同じように、数値を純粋なアルファベットの全単射ヘキサビゲシマルに変換するのに問題があります。

これが私のコードのバージョンですが、必要な出力が得られませんでした:

    var toHexvg = function(a){
     var x ='';
     var let = "_ abcdefghijklmnopqrstuvwxyz";
     var len = let.length;
     var b = a;
     var cnt = 0;
     var y = Array();
     行う{
      a =(a-(a%len))/ len;
      cnt ++;
     } while(a!= 0)
     a = b;
     var vnt = 0;
     行う{
      b + = Math.pow((len)、vnt)* Math.floor(a / Math.pow((len)、vnt + 1));
      vnt ++;
     } while(vnt!= cnt)
     var c = b;
     行う{
      y.unshift(c%len);
      c =(c-(c%len))/ len;
     } while(c!= 0)
     for(var i in y)x + = let [y [i]];
     xを返します。
    }

私の努力の最良の成果は次のa b c d ... y z ba bb bcとおりです。-上記の実際のコードではありませんが。意図された出力はであると想定されますa b c ... y z aa ab ac ... zz aaa aab aac ... zzzzz aaaaaa aaaaab、あなたは絵を手に入れます。

基本的に、私の問題は、関数ではなく「数学」を実行することにあります。最終的に私の質問は、Microsoft Excelのように、[想定される]無限大まで、ヘキサビゲシマル変換で数学を実行する方法です。

そして、可能であれば、ソースコードをよろしくお願いします。

4

7 に答える 7

13

さて、これが私の試みです。シーケンスを「a」(0を表す)で開始し、次のように実行することを想定しています。

a, b, c, ..., y, z, aa, ab, ac, ..., zy, zz, aaa, aab, ...

これは機能し、うまくいけばある程度意味があります。ファンキーな線は、0が空の文字列で表され、「a」が1になるなど、数学的に意味があるためです。

alpha = "abcdefghijklmnopqrstuvwxyz";

function hex(a) {
  // First figure out how many digits there are.
  a += 1; // This line is funky
  c = 0;
  var x = 1;      
  while (a >= x) {
    c++;
    a -= x;
    x *= 26;
  }

  // Now you can do normal base conversion.
  var s = "";
  for (var i = 0; i < c; i++) {
    s = alpha.charAt(a % 26) + s;
    a = Math.floor(a/26);
  }

  return s;
}

ただし、単純に順番に印刷する場合は、はるかに効率的な方法があります。たとえば、再帰やプレフィックスなどを使用します。

于 2011-12-22T13:31:52.387 に答える
3

@ user826788はすでに動作するコードを投稿していますが(これはさらに3分の1速いです)、ここで投稿を見つける前に行った自分の作業を投稿します(「hexavigesimal」という単語を知らなかったため)。ただし、逆の機能も含まれています。開始リスト要素をから変換するために使用するので、a=1を使用することに注意してください。

aa) first
ab) second

<ol type="a" start="27">
<li>first</li>
<li>second</li>
</ol>

function linum2int(input) {
    input = input.replace(/[^A-Za-z]/, '');
    output = 0;
    for (i = 0; i < input.length; i++) {
        output = output * 26 + parseInt(input.substr(i, 1), 26 + 10) - 9;
    }
    console.log('linum', output);
    return output;
}

function int2linum(input) {

    var zeros = 0;
    var next = input;
    var generation = 0;
    while (next >= 27) {
        next = (next - 1) / 26 - (next - 1) % 26 / 26;
        zeros += next * Math.pow(27, generation);
        generation++;
    }
    output = (input + zeros).toString(27).replace(/./g, function ($0) {
        return '_abcdefghijklmnopqrstuvwxyz'.charAt(parseInt($0, 27));
    });
    return output;
}

linum2int("aa"); // 27
int2linum(27); // "aa"
于 2012-07-16T14:05:21.993 に答える
2

次のように、再帰を使用してこれを実行できます。

const toBijective = n => (n > 26 ? toBijective(Math.floor((n - 1) / 26)) : "") + ((n % 26 || 26) + 9).toString(36);
// Parsing is not recursive
const parseBijective = str => str.split("").reverse().reduce((acc, x, i) => acc + ((parseInt(x, 36) - 9) * (26 ** i)), 0);

toBijective(1) // "a"
toBijective(27) // "aa"
toBijective(703) // "aaa"
toBijective(18279) // "aaaa"
toBijective(127341046141) // "overflow"

parseBijective("Overflow") // 127341046141
于 2019-05-09T02:44:47.210 に答える
0

数式からそれを計算する方法がわかりませんが、しばらくの間それをだまして、要求された列番号まで文字通りカウントアップする次のアルゴリズムを思いつきました。

var getAlpha = (function() {
    var alphas = [null, "a"],
        highest = [1];

    return function(decNum) {
        if (alphas[decNum])
            return alphas[decNum];

        var d,
            next,
            carry,
            i = alphas.length;

        for(; i <= decNum; i++) {
            next = "";
            carry = true;
            for(d = 0; d < highest.length; d++){
                if (carry) {
                    if (highest[d] === 26) {
                        highest[d] = 1;
                    } else { 
                        highest[d]++;
                        carry = false;
                    }
                }
                next = String.fromCharCode(
                          highest[d] + 96)
                     + next;
            }
            if (carry) {
                highest.push(1);
                next = "a" + next;
            }
            alphas[i] = next;
        }

        return alphas[decNum];
    };
})();


alert(getAlpha(27));     // "aa"
alert(getAlpha(100000)); // "eqxd"

デモ: http: //jsfiddle.net/6SE2f/1/

配列は、「桁」ごとに配列要素を持つ現在の最大数を保持しますhighest(要素0は最下位の「桁」です)。

bdwgn上記を開始したとき、同じ値が再度要求された場合に時間を節約するために、計算された各値をキャッシュすることは良い考えのように見えましたが、実際には(Chromeでは)1,000,000番目の値( )とを計算するのに約3秒しかかかりませんでした10,000,000番目の値(uvxxk)を計算するために約20秒。キャッシュを削除すると、10,000,000番目の値になるまで約14秒かかりました。

于 2011-12-22T13:37:43.967 に答える
0

今夜早くこのコードを書き終えたところですが、いまいましいものに何と名前を付けるかを探求しているときに、この質問を見つけました。ここにあります(誰かがそれを使用したいと思う場合に備えて):

/**
 * Convert an integer to bijective hexavigesimal notation (alphabetic base-26).
 *
 * @param {Number} int - A positive integer above zero
 * @return {String} The number's value expressed in uppercased bijective base-26
 */
function bijectiveBase26(int){
    const sequence    = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    const length      = sequence.length;

    if(int <= 0)      return int;
    if(int <= length) return sequence[int - 1];


    let index  = (int % length) || length;
    let result = [sequence[index - 1]];

    while((int = Math.floor((int - 1) / length)) > 0){
        index = (int % length) || length;
        result.push(sequence[index - 1]);
    }

    return result.reverse().join("")
}
于 2016-01-17T14:23:01.990 に答える
0

私は今日、仕事のためにこれと同じ問題を解決しなければなりませんでした。私の解決策はElixirで書かれており、再帰を使用していますが、その考え方を平易な英語で説明しています。

変換の例を次に示します。

0-> "A"、1-> "B"、2-> "C"、3-> "D"、.. 25-> "Z"、26-> "AA"、27-> "AB" 、..。

一見、通常の26ベースのカウントシステムのように見えるかもしれませんが、残念ながらそれほど単純ではありません。「問題」は、次のことに気付くと明らかになります。

A = 0
AA = 26

これは、通常のカウントシステムとは相容れません。通常のカウントシステムでは、「0」は、その単位以外の小数点以下の桁にある場合、「1」として動作しません。

アルゴリズムを理解するために、より単純ですが同等の2進数システムを考えてみましょう。

A = 0
B = 1
AA = 2
AB = 3
BA = 4
BB = 5
AAA = 6

通常の2進数カウントシステムでは、2の累乗(1、2、4、8、16)をとることで小数点以下の桁数の「値」を決定でき、2進数の値は、各桁にその桁の桁数を掛けて計算されます。価値。例:10101 = 1 *(2 ^ 4)+ 0 *(2 ^ 3)+ 1 *(2 ^ 2)+ 0 *(2 ^ 1)+ 1 *(2 ^ 0)= 21

より複雑なABシステムでは、小数点以下の値が次のようになっていることがわかります。

1, 2, 6, 14, 30, 62

パターンは、それ自体がであることを示しています(previous_unit_place_value + 1) * 2。そのため、次に低い単位の場所の値を取得するには、2で除算して1を減算します。

これは、ベース26システムに拡張できます。単純に26で割り、1を引きます。

これで、通常の基数10の数値を特殊な基数26に変換する式が明らかになりました。入力がであるとしましょうx

  1. アキュムレータリストを作成しますl
  2. xが26未満の場合は、設定l = [x | l]して手順5に進みます。それ以外の場合は続行します。
  3. xを2で割ります。床の結果はdで、余りはrです。
  4. アキュムレータリストの先頭として残りをプッシュします。すなわちl = [r | l]
  5. (d-1)を入力としてステップ2に進みます。例:x = d - 1
  6. """のすべての要素をl対応する文字に変換します。0->Aなど。

それで、最後に、これがエリクサーで書かれた私の答えです:

defmodule BijectiveHexavigesimal do
  def to_az_string(number, base \\ 26) do
    number
    |> to_list(base)
    |> Enum.map(&to_char/1)
    |> to_string()
  end

  def to_09_integer(string, base \\ 26) do
    string
    |> String.to_charlist()
    |> Enum.reverse()
    |> Enum.reduce({0, nil}, fn
      char, {_total, nil} ->
        {to_integer(char), 1}

      char, {total, previous_place_value} ->
        char_value = to_integer(char + 1)
        place_value = previous_place_value * base
        new_total = total + char_value * place_value
        {new_total, place_value}
    end)
    |> elem(0)
  end

  def to_list(number, base, acc \\ []) do
    if number < base do
      [number | acc]
    else
      to_list(div(number, base) - 1, base, [rem(number, base) | acc])
    end
  end

  defp to_char(x), do: x + 65
end

単にとして使用しますBijectiveHexavigesimal.to_az_string(420)。オプションの「ベース」引数も受け入れます。

OPがJavascriptについて質問したことは知っていますが、後世のためにElixirソリューションを提供したいと思いました。

于 2022-02-25T04:53:02.860 に答える
-2

aを表し0、をz表し25ます。したがって、後の数字z26、です。つまり1*26 + 0ba正しいです。(そして後の数字zzzzzはですbaaaaa。)

于 2011-12-22T11:56:19.580 に答える