9

一連の数値を、個々の値とその位置を保持する単一の数値に変換したいと考えています。たとえば、次のシーケンスが提供されます-

1,6,7,8,9,45,67

ここで、たとえば、単純な加算、つまり 1+6+7+8+9+45+67 を適用すると、数値が生成されます。しかし、それからいいえ。個々の番号を順序付け [つまり、1、6、7、8、9、...] で抽出することはできません。

あいまいな推論なしでこの機能を実現する方法はありますか (つまり、数値から一意の数値セットが 1 つだけ抽出されます)。その数値から個々の要素を取得するのに役立つ数学関数はありますか?

4

8 に答える 8

10

これをベースNの数値に変換できます。ここで、Nは、入力シーケンスに表示される最大値より1つ大きくなります。

アップデート

さまざまなコメントに基づいて、より実装しやすい代替ソリューションを提供したいと思います。シーケンスをUTF-8でエンコードされた文字列と見なし、カスタム辞書でハフマンコーディングを使用してコンパクトな表現を実現できます。

カスタムディクショナリを使用すると、非常に一般的な文字を非常に少ないビットで格納できます(たとえば、シーケンスセパレータ'、'および個々の文字'0' .. '9'は、わずか3ビットで格納できますが、他の数値も格納できます。統計的に発生する可能性が高いとわかったものは、短いビットシーケンスで保存できます。たとえば、「42」が頻繁に発生する場合は、「42」をほんの数ビットで保存できます。

'、'、および'0'から'9'にのみ特別なコードを割り当てる場合、シーケンスメンバーを区切るコンマを保持したまま、入力文字列の1文字あたりの平均は4ビット未満になります。一般的な複数文字の部分文字列を見つけて辞書に追加すると、その比率が向上するだけです。

カスタムディクショナリを使用するということは、ディクショナリがよく知られているため、圧縮データのヘッダーにディクショナリを格納する必要がないことも意味します。

私はSharpZipLibを使用してこのようなことをしました

http://www.icsharpcode.net/opensource/sharpziplib/

http://community.sharpdevelop.net/forums/p/8255/23219.aspx

zlibで行うのも簡単です

小さなデータの圧縮

于 2012-09-01T16:19:12.193 に答える
4

有限のシーケンスに対して数学的には可能ですが、必要な数が非常に急速に大きくなるため、あまり実用的ではありません.シーケンスとそれ以上の整数。

このような関数の簡単な例として、シーケンス [1,6,7,8,9,45,67] を値 2 1 * 3 6 * 5 7 * 7 8 * 11 9 * 13 45 * 17 67にマップします。 . 底は素数で、ベキは数列の要素です。

逆マッピングは除算によって計算されます。値を除算できる回数は2、シーケンスの最初の要素などです。値の最大の素因数は、シーケンスの長さを示します。

数列と正の数を許可する場合0は、素数を累乗するときにすべての要素に 1 を追加します。または、代わりに の累乗を使用し2てシーケンスの長さを指定し、 で始まる要素のエンコードを開始し3ます。

ゲーデルは、不完全性定理の証明でこのようなエンコーディングを使用しました。

Kendall Frey が言うように、整数の各無限シーケンスを別の整数にマップする関数を定義することはできません。{true, false}これは、自然数のベキ集合が可算でないというカントールの証明の結果です。整数からの要素のすべての無限シーケンスは言うまでもなく、からの要素のすべての無限シーケンスを整数に単射的にマッピングすることさえできません。

より実用的なアプローチについては、整数のシーケンスを数値ではなくバイトのシーケンスとしてエンコードするという観点から考えてください。バイトの有限シーケンスはバイナリ値と簡単に見なすことができます。したがって、それは数値であり、実際にはそのように使用することはありません。サンプル シーケンスの一般的な表現はバイト シーケンスです[1,6,7,8,9,45,67]。たとえば、JSON で使用されます。これは 136 ビットの数値です。このマッピングを逆にする数学関数には、256 の累乗を法とする算術演算、48 の減算、10 の乗算などが含まれます :-)

于 2012-09-01T18:28:13.723 に答える
2

あなたのシーケンスが呼び出されたとしましょう。 n の桁数をs 定義します。len(n)

結果の最初の桁はlen(s[0])で、次のlen(s[0])桁は数値s[0]です。len(s[1])次にand などを追加しますs[1]

これは、最大 9 桁の数字で機能します。

于 2012-09-01T16:23:42.277 に答える
1

あなたの数の範囲が無限であるならば、あなたはそうすることができません。

数え切れないほどの自然数のべき集合。これは、数値のセットと数値の間のマッピングを提供できないことを意味します。

数値がたとえば32ビットに制限されている場合にできることは、数値を長い2進数に連結し、それらをバイトのシーケンスとして、おそらくBigNumとして格納することです。

于 2012-09-01T16:20:34.390 に答える
0

0,1ケースをチェックするように更新されました。

異なる番号を001で区切ります。

番号内の00との混同を避けるために、番号に0が表示されるたびに、01に置き換えてください。

デコードするには、001で分割します。すべての01を0に置き換えます。

于 2012-09-01T16:19:46.437 に答える
0

私に思い浮かんだもう一つの答え。各数値を平衡 3 進数にエンコードし、トリットあたり 2 ビットを使用します (例: 0=00; +1=01; -1=10)。残りのビット ペア (たとえば、11) は要素マーカーの終了であり、シーケンスの終了のために繰り返されます。短所:大きな値が予想される場合、プレフィックスコードよりもスペース効率が低くなります。長所: 1) ほとんどの値が小さいため、スペース効率が向上します。2) エンコード/デコードが簡単。3) 負の値を直接表します。

于 2014-08-14T14:49:05.900 に答える
0

これは、Elias オメガ コーディングなどのユニバーサル コードを使用します(または任意のプレフィックス コードですが、ユニバーサル コードは、いくつかの望ましい特性を持つプレフィックス コードです)。プレフィックス コードは、ビット シーケンス (つまり、数値) をプレフィックスとしてエンコードします。このプレフィックスは、残りの数を構成するビット数を決定するために基本的に必要な情報を提供します。

1) コードを使用して、シーケンス内の要素の数を表します。2) 次に、コードを使用して各要素を表します。

于 2014-08-14T03:31:23.517 に答える