否定形

負の基数または負の基数)は、非標準的な位取り記数法を構成するために用いられる。他の位取り記数法と同様に、各位はシステムの基数の適切なべき乗の倍数を保持する。ただし、その基数は負である。つまり、ある自然数r ( r ≥ 2 ) に対して、基数bはrに等しい

負基数システムは標準的な位取り記数法と同じ数値をすべて扱えますが、正数と負数の両方をマイナス符号(コンピュータ表現では符号ビット)なしで表すことができます。この利点は、算術演算の複雑さの増加によって相殺されます。負符号に通常含まれる情報を格納しなければならないため、負基数の数は正基数の数よりも1桁長くなることがよくあります。

負の基数位取り記数法の一般的な名称は、対応する正の基数体系の名称に接頭辞 「nega-」を付けることで形成される。例えば、負十進数(基数-10)は十進数(基数10)に負二進数(基数-2)は二進数(基数2)に、三進数(基数-3)は三進数(基数3)に、負四進数(基数-4)は四進数(基数4)に対応する。[1] [2]

表現が何を意味するか考えてみましょう負数法では12243 、その底bは-10です。

の倍数
(-10) 4 = 10000(-10) 3 = -1000(−10)2 = 100(−10)1 = −10(−10)0 = 1
12243

表現12243 −10(負の10進数表記を意図している)は、8,163 10を10進数で表すと、10,000 + (-2,000) + 200 + (-40) + 3 =8163

備考

一方、−8163 10を10進数で表すと負数では9977 −10です。

歴史

負の基数は、 1885年にヴィットリオ・グリュンワルドによって『Giornale di Matematiche di Battaglini』に掲載されたモノグラフで初めて考察されました[3]グリュンワルドは、加算、減算、乗算、除算、平方根の抽出、割り切れるかどうかの判定、基数変換を実行するためのアルゴリズムを提示しました。負の基数は、後に1936年にAJケンプナーによって簡単に言及され、 [4] 1957年にズジスワフ・パウラックとA.ヴァクリッチによってより詳細に研究されました。[5]

ネガバイナリは、1957年から1959年にかけて製造された初期のポーランドのコンピュータBINEG(およびUMC )に実装されました。これは、ワルシャワ数学研究所のZ. PawlakとA. Lazarkiewiczのアイデアに基づいています[6] それ以降の実装はほとんどありませんでした。

ローレンス・リバモア国立研究所の浮動小数点圧縮アルゴリズムであるzfpは、数値の保存にnegabinaryを使用します。zfpのドキュメントによると、次のようになります。[7]

符号・絶対値表現とは異なり、負数バイナリの左端の1ビットは、数値の符号と概算絶対値を同時に符号化します。さらに、2の補数とは異なり、負数バイナリでは絶対値が小さい数値は符号に関わらず先頭に多くのゼロが付くため、符号化が容易になります。

表記法と使用法

基数をrと表記すると、すべての整数 a は次のように一意に表すことができます

ここで、各桁d kは0からr − 1 までの整数であり、先頭の桁d n > 0です(n = 0の場合を除く)。a の − r 基数展開文字列d n d n −1 ... d 1 d 0で表されます

したがって、負の基数システムは、基数が正であるものの、数字が部分的に負の範囲から取得される、平衡三進法などの符号付き数字表現と比較することができます。(下の表では、値が-1の数字は単一の文字Tとして書かれています。)

いくつかの数は、基数− rでも基数rでも同じ表現になります。例えば、100 から 109 までの数は、10進数でも負数でも同じ表現になります。同様に、

これは 2 進数では 10001、負の 2 進数では 10001 で表されます。

いくつかの数とその正の基数および対応する負の基数での展開は次のようになります。

10進数負の10進数2進数負の2進数3進数負三元数平衡三元数平衡負三元数四元数ネガクォータナリー
−1525−1111110001−1201220T11011T0−331301
−515−1011111−1221T11TT1−1123
−416−1001100−1122TT1T−1010
−317−111101−1010T010−311
−218−1010−211T111−212
−119−111−112TT−113
0000000000
1111111111
2210110221TTT22
33111111012010T033
441001001112111T110130
55101101121221TT11T11131
6611011010201101T011012132
7711111011211111T111113133
881000110002211210T10T20120
9910011100110010010010021121
1019010101111010110110110122122
1119110111111110210211T1TT23123
121921100111001102201101T030110
131931101111011112211111T131111
141941110100101122221TTTTT1T32112
151951111100111202101TT0TT1033113
1619610000100001212111TT1TT11100100
1719710001100011222121T0TTT0T101101
1819810010101102002001T00TT00102102

負の平衡三進法を除いて、負の整数の基数- r展開は偶数桁になり、非負の整数の基数- r展開は奇数桁になることに注意してください。

計算

ある数のr基数展開は、 rによる割り算を繰り返し、非負の余りを に記録し、最後の余りから順に連結することで求められます。a / b が c で余りが d の場合bc + d = aとなりしたがってd = abcなります正しい変換を得るには、 d が非負かつ最小となるようにcの値を選択する必要があります。以下の例の4行目では、これは次のことを意味します。

選択されなければならない — そして

たとえば、10進数の146を負の3進数に変換するには、次のようにします。

剰余を逆に読むと146 10 : 21102 –3の負数表現が得られます。

証明: −3 · (−3 · (−3 · (−3 · ( 2 ) + 1 ) + 1 ) + 0 ) + 2 = ((( 2 · (−3) + 1 ) · (−3) + 1 ) · (−3) + 0 ) · (−3) + 2

= 146 10。剰余を前方に読み進めると、負の数の最下位桁を先にする表現が得られます。

証明: 2 + ( 0 + ( 1 + ( 1 + ( 2 ) · −3 ) · −3) · −3 ) · −3 = 146 10 .

ほとんどのプログラミング言語では、負の数を負の数で割った結果(整数演算)は0に丸められ、通常は負の余りが残ります。このような場合、a = (− r ) c + d = ( − r ) c + dr + r = (− r )( c + 1) + ( d + r )となります。| d | < rであるため、( d + r )が正の余りとなります。したがって、このような場合に正しい結果を得るには、上記のアルゴリズムのコンピュータ実装において、商と余りにそれぞれ1とrを加算する必要があります。

実装コード例

negabinaryへ

C #
static string ToNegabinary ( int val ) { string result = string.Empty ;      while ( val != 0 ) { int残り= val % - 2 ; val = val / - 2 ;            if (剰余< 0 ) {剰余+= 2 ;+= 1 ; }       結果=剰余.ToString ( ) +結果; }    結果を返す; } 
C++
auto to_negabinary ( int value ) { std :: bitset < sizeof ( int ) * CHAR_BIT > result ; std :: size_t bit_position = 0 ;            while ( value != 0 ) { const auto div_result = std :: div ( value , -2 );           if ( div_result . rem < 0 ) value = div_result . quot + 1 ; else value = div_result . quot ;             result.set ( bit_position , div_result.rem ! = 0 ) ;    ++ビット位置; }  結果を返す; } 

C #
static string Negaternary ( int val ) { string result = string.Empty ;      while ( val != 0 ) { int残り= val % - 3 ; val = val / - 3 ;            if (剰余< 0 ) {剰余+= 3 ;+= 1 ; }       結果=剰余.ToString ( ) +結果; }    結果を返す; } 
Python
def negaternary ( i : int ) -> str : """10進数を負数に変換""" if i == 0 : digits = [ "0" ] else : digits = [] while i != 0 : i ,剰余= divmod ( i , - 3 ) if residual < 0 : i ,剰余= i + 1 ,剰余+ 3 digits .append ( str (剰余) ) return "" .join ( digits [ :: - 1 ] )                                         
>>>負三進数( 1000 ) '2212001'
コモンリスプ
( defun negaternary ( i ) ( if ( zerop i ) "0" ( let (( digits "" ) ( rem 0 )) ( loop while ( not ( zerop i )) do ( progn ( multiple-value-setq ( i rem ) ( truncate i -3 )) ( when ( minusp rem ) ( incf i ) ( incf rem 3 )) ( setf digits ( concatenate 'string ( write-to-string rem ) digits )))) digits )))                                        

負のベースに

Java
 import java.util.ArrayList ; import java.util.Collections ; public ArrayList <Integer> negativeBase ( int input , int base ) { ArrayList <Integer> result_rev = new ArrayList <> ( ) ; int number = input ; while ( number ! = 0 ) { int i = number % base ; number / = base ; if ( i < 0 ) { i + = Math.abs ( base ) ; number ++ ; } result_rev.add ( i ) ; } return Collections.reverse ( results_rev.clone ( ) ) ; }                                             

上記の例では、結果は整数のArrayListで返されるため、コードでは-10より小さい基数をどのように表現するかを考える必要がありません。結果を文字列として表示するには、基数と文字のマッピングを決定できます。例えば、以下のようになります。

import java.util.stream.Collectors ; final String alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@_" ; public String toBaseString ( ArrayList < Integer > lst ) { // base が 64 文字の範囲を超える場合は例外が発生しますreturn lst . stream (). map ( n -> alphabet [ n ] ). collect ( Collectors . join ( "" )); }              
オートリスプ
( defun negabase ( num baz / dig rst ) ;; NUM は任意の数値です。;; BAZ は [-10, -2] の範囲の任意の数値です。(これは文字列表記の方法によって強制されます。) ;; ;; NUM と BAZ は浮動小数点数の場合は整数に切り捨てられます (例: 14.25 は14 に、-123456789.87 は -123456789 に切り捨てられます)。( if ( and ( numberp num ) ( numberp baz ) ( <= ( fix baz ) -2 ) ( > ( fix baz ) -11 )) ( progn ( setq baz ( float ( fix baz )) num ( float ( fix num )) dig ( if ( = num 0 ) "0" "" )) ( while ( /= num 0 ) ( setq rst ( - num ( * baz ( setq num ( fix ( / num baz )))))) ( if ( minusp rst ) ( setq num ( 1+ num ) rst ( - rst baz ))) ( setq dig ( strcat ( itoa ( fix rst )) dig ))) dig ) ( progn ( prompt ( cond ( ( and ( not ( numberp num )) ( not ( numberp baz ))) "\n数値と負の基数が間違っています。" ) (( not ( numberp num )) "\n数値が間違っています。" ) (( not ( numberp baz )) "\n負の基数が間違っています。" ) ( t                                                                                                  "\nNegabase は [-10 -2] の範囲内になければなりません。" ))) ( princ )))) 

ショートカット計算

以下のアルゴリズムは、

  1. 入力はビット文字列で利用可能であり、(基数+2、数字は)でコード化されている(今日のほとんどのデジタルコンピュータと同様)。
  2. +add( ) と xor( ) 演算があり^、これらは(今日のほとんどのデジタルコンピュータと同様に)このようなビット列に対して演算される。
  3. 出力桁の集合は標準的である、すなわち基数
  4. 出力は同じビット文字列形式でコード化されますが、場所の意味は異なります。

negabinaryへ

負の2進数(基数-2、桁数)への変換は、驚くべきショートカットを可能にします(C言語での実装)。

uint32_t toNegaBinary ( uint32_t value ) // 標準バイナリで入力{ uint32_t Schroeppel2 = 0xAAAAAAAA ; // = 2/3*((2*2)^16-1) = ...1010 return ( value + Schroeppel2 ) ^ Schroeppel2 ; // 排他的 OR // 要素の文字列として解釈される unsigned int の結果 ε {0,1} (ビット) }             

同じショートカット計算の JavaScript ポート:

関数toNegaBinary () { const Schroeppel2 = 0xAAAAAAAA ; // C と同様に変換し、NegaBinary String に変換しますreturn ( ( value + Schroeppel2 ) ^ Schroeppel2 )。toString ( 2 ); }                 

このアルゴリズムは、SchroeppelによってHAKMEM (1972)の項目128で初めて説明されました。Wolfram MathWorldには、D. Librik(Szudzik)によるWolfram言語のバージョンが文書化されています。[8]

負の4進数へ

負の4進数(基数-4、数字は)への変換では、同様のショートカットが可能です(C言語での実装)。

uint32_t toNegaQuaternary ( uint32_t value ) // 標準バイナリで入力{ uint32_t Schroeppel4 = 0xCCCCCCCC ; // = 4/5*((2*4)^8-1) = ...11001100 = ...3030 return ( value + Schroeppel4 ) ^ Schroeppel4 ; // 排他的論理和// 結果の unsigned int は要素 ε {0,1,2,3} (ビットのペア) の文字列として解釈されます}             

同じショートカット計算の JavaScript ポート:

function toNegaQuaternary ( value ) { const Schroeppel4 = 0xCCCCCCCC ; // C と同じように変換し、NegaQuaternary 文字列に変換しますreturn ( ( value + Schroeppel4 ) ^ Schroeppel4 ). toString ( 4 ); }                 

算術演算

以下は負の二進法の算術演算について説明します。より大きな基数での計算も同様です

加算

負の2進数の加算は、最下位ビットから始めてビット単位で進行します。各加数のビットは、前のビット(LSBが0)からの(バランスの取れた3進数の)キャリーと合計されます。この合計は、表に示すように、次の反復のための出力ビットとキャリーに分解されます

合計出力コメント
ビットキャリー
−2010 −20101 −2−2 は減算時にのみ発生します。
−1011 −21101 −2
0000 −20000 −2
1001 −21000 −2
2110 −20−111 −2
3111 −21−111 −23は加算時にのみ発生します。

例えば、この表の2行目は、−1 = 1 + 1 × −2 という事実を表し、5行目は2 = 0 + −1 × −2 を 表しています

例えば、1010101 −2 (1 + 4 + 16 + 64 = 85)と1110100 −2 (4 + 16 − 32 + 64 = 52)を足すと、

キャリー: 1 −1 0 −1 1 −1 0 0 0最初の加数: 1 0 1 0 1 0 12番目の加数: 1 1 1 0 1 0 0 + --------------------------数字: 1 −1 2 0 3 −1 2 0 1ビット(結果): 1 1 0 0 1 1 0 0 1キャリー: 0 1 −1 0 −1 1 −1 0 0

結果は110011001 −2 (1 − 8 + 16 − 128 + 256 = 137)になります。

別の方法

2つの負の2進数を加算する際、繰り上がりが発生するたびに、追加の繰り上がりを次のビットに伝播させる必要があります。上記と同じ例を考えてみましょう

追加キャリー: 1 1 1 0 1 0 0 0 キャリー: 0 1 1 0 1 0 0 0最初の加数: 1 0 1 0 1 0 12番目の加数: 1 1 1 0 1 0 0 + --------------------------答え: 1 1 0 0 1 1 0 0 1

負の2進数全加算器

全加算回路は、負の2進数で数を加算するように設計できます。加算と繰り上がりを計算するには、以下のロジックが使用されます。[9]

負の二進数の増分

負の二進数の増分は、次の式を使って行うことができます。[10]

(この式の演算は、通常の 2 進数に対する演算として解釈されます。たとえば、は 1 ビットの 2 進左シフトです。)

引き算

引き算をするには、2番目の数の各ビットに-1を掛け、上記と同じ表を使って数を足します

例えば、1101001 −2 (1 − 8 − 32 + 64 = 25) から 1110100 −2 (4 + 16 − 32 + 64 = 52) を引くと、

キャリー: 0 1 −1 1 0 0 0最初の数字: 1 1 0 1 0 0 12番目の数字: −1 −1 −1 0 −1 0 0 + --------------------数字: 0 1 −2 2 −1 0 1ビット(結果): 0 1 0 0 1 0 1キャリー: 0 0 1 −1 1 0 0

結果は100101 −2 (1 + 4 −32 = −27)になります。

単項否定xは、ゼロからの二項減算0 − xとして計算できます

掛け算と割り算

左にシフトすると-2倍になり、右にシフトすると-2で割ります

掛け算をするには、通常の10 進数2 進数と同じように掛け算しますが、数字を加算するときに、繰り上がりを加算するための負の 2 進数規則を使用します。

最初の数字: 1 1 1 0 1 1 02番目の数字: 1 0 1 1 0 1 1 × ------------------------------------- 1 1 1 0 1 1 0 1 1 1 0 1 1 0 1 1 1 0 1 1 0 1 1 1 0 1 1 0 1 1 1 0 1 1 0 + -------------------------------------キャリー: 0 −1 0 −1 −1 −1 −1 −1 −1 0 −1 0 0番号: 1 0 2 1 2 2 2 3 2 0 2 1 0ビット(結果): 1 0 0 1 0 0 0 1 0 0 0 1 0キャリー: 0 −1 0 −1 −1 −1 −1 −1 −1 0 −1 0 0

各列について、数値繰り上がり を加算し、その合計を -2 で割って新しい繰り上がりを取得し、結果のビットを剰余として返します。

負の二進数の比較

通常の符号なし2進数比較器を少し調整することで、負の2進数を比較することができます。数とを比較する際は両方の数の奇数ビットを反転します。その後、標準的な符号なし比較器を使用して、とを比較します[11]

分数

基数-r表現は、もちろん基数点を超えて繰り越すことができ、非整数の表現が可能になります

正の底のシステムと同様に、終了表現は分母が底の累乗である分数に対応し、繰り返し表現は他の有理数に対応しますが、その理由も同じです。

一意でない表現

正の基数体系では整数と有限小数が一意でない表現(例えば、10進数では0.999…= 1 )を持つのに対し、負の基数体系では整数は単一の表現しか持ちません。しかし、一意でない表現を持つ有理数は存在します。{0, 1, …, t }の数字に対して、最大の桁と

我々は

    および

したがって、分数が加算されたすべての数には、2つの異なる表現があります

例えば、負三元数、すなわちとの場合、

このような一意でない表現は、整数部がそれぞれ0と1である最大と最小の表現を考え、それらが等しいことに気づくことで見つけることができます。(実際、これは任意の整数基数システムで機能します。)このように一意でない表現が可能な有理数は、次の形式のものです

虚数基数

複素数基数系に関する主要記事

負の基数を使用すると負の符号を明示的に付けずに負の数を表現できるのと同様に、虚数基数を使用するとガウス整数を表現できますドナルド・クヌースは1955年に4分の1虚数基数(基数2i)を提案しました。 [12]

参照

参考文献

  1. ^ ドナルド・クヌース(1998年)『コンピュータプログラミングの芸術』第2巻(第3版)、 204~ 205ページ クヌースは負の2進数と負の10進数の両方について言及しています。
  2. ^ 負三進法については、Petkovšek, Marko (1990)「Ambiguous numbers are dense」(アメリカ数学月刊誌97 (5): 408– 411、doi :10.2307/2324393、ISSN  0002-9890、JSTOR  2324393、MR  1048915)で簡単に説明されている。
  3. ^ ヴィットリオ・グリュンヴァルト。 Intorno all'aritmetica dei sistemi numerici a base negativa con particolare riguardo al sistema numerico a base negativo-10male per lo Studio delle sue Analie coll'aritmetica ordinaria (10 進数)、 Giornale di Matematiche di Battaglini (1885)、203-221、367
  4. ^ ケンプナー, AJ (1936)、「異常な数え方」、アメリカ数学月刊誌43 (10): 610– 617、doi :10.2307/2300532、JSTOR  2300532、MR  1523792負の基数に関する唯一の言及は610ページの脚注で、「1未満の正の数と負の数は、処理手順を若干変更し、使用する数字のセットに適切な制限を加えることで、基数として使用できます。」と書かれています。
  5. ^ Pawlak, Z.; Wakulicz, A. (1957)、「デジタルコンピュータの算術計における負の基底を持つ展開の使用」、Bulletin de l'Académie Polonaise des Sciences、Classe III、5 : 233– 236
  6. ^ Marczynski, RW、「ポーランドのコンピューティングの最初の7年間」、2011年7月19日アーカイブ IEEE Annals of the History of Computing、第2巻、第1号、1980年1月
  7. ^ "アルゴリズム — zfp 1.0.1 ドキュメント". zfp.readthedocs.io
  8. ^ MathWorldのNegabinaryリンクを参照してください。具体的な参考文献は以下の通りです。
    • Szudzik, M. 「プログラミングチャレンジ:Mathematicaプログラミングコンテスト」 Wolframテクノロジーカンファレンス、1999年。
    • Schroeppel, R. Beeler, M.; Gosper, RW; Schroeppel, R. HAKMEMの項目128。マサチューセッツ州ケンブリッジ:MIT人工知能研究所、メモAIM-239、p. 24、1972年2月。http://www.hakmem.org/#item128
  9. ^ フランシス、ユウ;スガンダ、ジュタムリア。シズフオ、殷(2001 年 9 月 4 日)。情報光学の紹介。学術出版局。 p. 498.ISBN 9780127748115
  10. ^ 「なぜ次の式は負の2進数(-2を底とする数)を増分するのでしょうか?」2016年8月29閲覧
  11. ^ ムルゲサン、サン (1977). 「2値演算を用いたマイナス2値演算回路」。電子回路とシステムに関する IEE ジャーナル1 (2): 77.土井:10.1049/ij-ecs.1977.0005。
  12. ^ D. Knuth著『コンピュータプログラミングの技法』第2巻第3版、Addison-Wesley社、205ページ、「位置数システム」

参考文献

Retrieved from "https://en.wikipedia.org/w/index.php?title=Negative_base&oldid=1283667536"