Se puede utilizar una base negativa (o radix negativa) para construir un sistema de numeración posicional no estándar . Al igual que otros sistemas de valor posicional, cada posición contiene múltiplos de la potencia apropiada de la base del sistema; pero esa base es negativa, es decir, la base b es igual a − r para algún número natural r ( r ≥ 2 ).
Los sistemas de base negativa admiten los mismos números que los sistemas posicionales estándar, pero tanto los números positivos como los negativos se representan sin utilizar el signo menos (o, en la representación informática, el bit de signo ). Esta ventaja se ve contrarrestada por una mayor complejidad de las operaciones aritméticas. La necesidad de almacenar la información que normalmente contiene el signo negativo suele resultar en que un número de base negativa tenga un dígito más que su equivalente de base positiva.
Los nombres comunes de los sistemas de numeración posicional de base negativa se forman anteponiendo el prefijo nega- al nombre del sistema de base positiva correspondiente; por ejemplo, negadecimal (base −10) corresponde a decimal (base 10), negabinario (base −2) a binario (base 2), negaternario (base −3) a ternario (base 3) y negacuaternario (base −4) a cuaternario (base 4). [ 1 ] [ 2 ]
Ejemplo
Consideremos qué se entiende por representación.12243 en el sistema negadecimal, cuya base b es −10:
La representación12243 −10 (que se supone que es notación negadecimal) es equivalente a8,163 10 en notación decimal, porque 10,000 + (−2,000) + 200 + (−40) + 3 =8163 .
- Observación
Por otro lado,−8163 10 en decimal se escribiría9977 −10 en negativodecimal.
Historia
Las bases numéricas negativas fueron consideradas por primera vez por Vittorio Grünwald en una monografía publicada en 1885 en el Giornale di Matematiche di Battaglini . [ 3 ] Grünwald proporcionó algoritmos para realizar sumas, restas, multiplicaciones, divisiones, extracción de raíces, pruebas de divisibilidad y conversión de bases. Posteriormente, A. J. Kempner mencionó las bases negativas de pasada en 1936 [ 4 ] y Zdzisław Pawlak y A. Wakulicz las estudiaron con mayor detalle en 1957. [ 5 ]
El sistema negabinario se implementó en la primera computadora polaca BINEG (y UMC ), construida entre 1957 y 1959, basada en ideas de Z. Pawlak y A. Lazarkiewicz del Instituto Matemático de Varsovia . [ 6 ] Desde entonces, las implementaciones han sido escasas.
zfp, un algoritmo de compresión de punto flotante del Laboratorio Nacional Lawrence Livermore , utiliza el sistema negabinario para almacenar números. Según la documentación de zfp: [ 7 ]
A diferencia de las representaciones de signo y magnitud, el bit más a la izquierda en el sistema negabinario codifica simultáneamente el signo y la magnitud aproximada de un número. Además, a diferencia del complemento a dos, los números de magnitud pequeña tienen muchos ceros iniciales en el sistema negabinario, independientemente del signo, lo que facilita la codificación.
Notación y uso
Denotando la base como − r , cada entero a puede escribirse de forma única como
donde cada dígito d k es un entero de 0 a r − 1 y el dígito principal d n > 0 (a menos que n = 0 ). La expansión en base − r de a viene dada por la cadena d n d n −1 ... d 1 d 0 .
Los sistemas de base negativa pueden compararse, por lo tanto, con las representaciones de dígitos con signo , como el sistema ternario balanceado , donde la base es positiva pero los dígitos se toman de un rango parcialmente negativo. (En la tabla siguiente, el dígito con valor −1 se escribe como el carácter T).
Algunos números tienen la misma representación en base − r que en base r . Por ejemplo, los números del 100 al 109 tienen las mismas representaciones en decimal y negadecimal. De manera similar,
y se representa mediante 10001 en binario y 10001 en negabinario.
Algunos números con sus expansiones en varias bases positivas y negativas correspondientes son:
Tenga en cuenta que, con la excepción del ternario negativo balanceado, las expansiones en base − r de los enteros negativos tienen un número par de dígitos, mientras que las expansiones en base − r de los enteros no negativos tienen un número impar de dígitos.
Cálculo
La expansión en base − r de un número se puede encontrar dividiendo repetidamente por − r y registrando los restos no negativos eny concatenando esos restos, comenzando por el último. Nótese que si a / b es c con resto d , entonces bc + d = a y, por lo tanto , d = a − bc . Para llegar a la conversión correcta, el valor de c debe elegirse de manera que d sea no negativo y mínimo. Para la cuarta línea del siguiente ejemplo, esto significa que
tiene que ser elegido, y noni
Por ejemplo, para convertir 146 en decimal a negaternario:
Leyendo los restos hacia atrás obtenemos la representación negaternaria de 146 10 : 21102 –3 .
- Prueba: −3 · (−3 · (−3 · (−3 · ( 2 ) + 1 ) + 1 ) + 0 ) + 2 = ((( 2 · (−3) + 1 ) · (−3) + 1 ) · (−3) + 0 ) · (−3) + 2 = 146 10 .
Leyendo los restos hacia adelante podemos obtener la representación negaternaria con el dígito menos significativo primero.
- Prueba: 2 + ( 0 + ( 1 + ( 1 + ( 2 ) · −3 ) · −3) · −3 ) · −3 = 146 10 .
Nótese que en la mayoría de los lenguajes de programación , el resultado (en aritmética de enteros) de dividir un número negativo entre otro negativo se redondea hacia cero, dejando generalmente un resto negativo. En tal caso, tenemos a = (− r ) c + d = (− r ) c + d − r + r = (− r )( c + 1) + ( d + r ) . Como | d | < r , ( d + r ) es el resto positivo. Por lo tanto, para obtener el resultado correcto en este caso, las implementaciones informáticas del algoritmo anterior deberían sumar 1 y r al cociente y al resto, respectivamente.
Código de implementación de ejemplo
A negabinario
DO#
cadena estática ToNegabinary ( int val ) { cadena resultado = cadena . Empty ;mientras ( val != 0 ) { int resto = val % - 2 ; val = val / - 2 ;Si ( resto < 0 ) { resto += 2 ; valor += 1 ; }resultado = resto.ToString ( ) + resultado ; }devolver resultado ; }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 ;resultado.establecer ( bit_position , div_result.rem ! = 0 ) ;++ bit_position ; }devolver resultado ; }A negaternario
DO#
cadena estática Negaternary ( int val ) { cadena resultado = cadena . Empty ;mientras ( val != 0 ) { int resto = val % - 3 ; val = val / - 3 ;Si ( resto < 0 ) { resto += 3 ; valor += 1 ; }resultado = resto.ToString ( ) + resultado ; }devolver resultado ; }Pitón
def negaternary ( i : int ) -> str : """Decimal a negaternary""" if i == 0 : digits = [ "0" ] else : digits = [] while i != 0 : i , remainder = divmod ( i , - 3 ) if remainder < 0 : i , remainder = i + 1 , remainder + 3 digits . append ( str ( remainder )) return "" . join ( digits [:: - 1 ])>>> negaternario ( 1000 ) '2212001'Lisp común
( 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 )))A cualquier base negativa
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 ( result_rev.clone ( ) ) ; }Lo anterior proporciona el resultado en un ArrayList de enteros, de modo que el código no tiene que gestionar cómo representar una base menor que -10. Para mostrar el resultado como una cadena, se puede definir una correspondencia entre la base y los caracteres. Por ejemplo:
import java.util.stream.Collectors ; final String alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@_" ; public String toBaseString(ArrayList<Integer> lst) { // Se lanzaría una excepción si la base está más allá de los 64 caracteres posibles return lst.stream ( ). map ( n - > alphabet [ n ] ) . collect ( Collectors.joining ( "" ) ); }AutoLisp
( defun negabase ( num baz / dig rst ) ;; NUM es cualquier número. ;; BAZ es cualquier número en el intervalo [-10, -2]. (Esto se debe a cómo hacemos la notación de cadena.) ;; ;; NUM y BAZ se truncarán a un entero si son flotantes (por ejemplo, 14.25 ;; se truncará a 14, -123456789.87 a -123456789, etc.). ( 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 ))) "\nNúmero y base negativa incorrectos." ) (( not ( numberp num )) "\nNúmero incorrecto." ) (( not ( numberp baz )) "\nBase negativa incorrecta." ) ( t"\nLa base negativa debe estar dentro del intervalo [-10 -2]." ))) ( princ ))))Cálculo abreviado
Los siguientes algoritmos asumen que
- La entrada está disponible en cadenas de bits y codificada en (base +2; dígitos en) (como en la mayoría de las computadoras digitales actuales),
- existen operaciones de suma (
+) y xor (^), que operan sobre dichas cadenas de bits (como en la mayoría de las computadoras digitales actuales), - el conjuntode dígitos de salida es estándar, es decir.con base,
- La salida está codificada en el mismo formato de cadena de bits, pero el significado de los lugares es diferente.
A negabinario
La conversión a negabinario (base −2; dígitos en) permite un atajo notable (implementación en C):
uint32_t toNegaBinary ( valor uint32_t ) // entrada en binario estándar { uint32_t Schroeppel2 = 0xAAAAAAAA ; // = 2/3*((2*2)^16-1) = ...1010 retorno ( valor + Schroeppel2 ) ^ Schroeppel2 ; // eXclusive OR // resultante unsigned int que se interpretará como una cadena de elementos ε {0,1} (bits) }Versión en JavaScript para el mismo cálculo abreviado:
función toNegaBinary ( valor ) { const Schroeppel2 = 0xAAAAAAAA ; // Convertir como en C, luego convertir a una cadena NegaBinary return ( ( valor + Schroeppel2 ) ^ Schroeppel2 ). toString ( 2 ); }El algoritmo fue descrito por primera vez por Schroeppel en HAKMEM (1972) como el elemento 128. Wolfram MathWorld documenta una versión en el lenguaje Wolfram por D. Librik (Szudzik). [ 8 ]
A negacuaternario
La conversión a negacuaternario (base −4; dígitos en) permite un atajo similar (implementación en C):
uint32_t toNegaQuaternary ( uint32_t value ) // entrada en binario estándar { uint32_t Schroeppel4 = 0xCCCCCCCC ; // = 4/5*((2*4)^8-1) = ...11001100 = ...3030 return ( value + Schroeppel4 ) ^ Schroeppel4 ; // OR exclusivo // el entero sin signo resultante se interpretará como una cadena de elementos ε {0,1,2,3} (pares de bits) }Versión en JavaScript para el mismo cálculo abreviado:
función toNegaQuaternary ( valor ) { const Schroeppel4 = 0xCCCCCCCC ; // Convertir como en C, luego convertir a cadena NegaQuaternary return ( ( valor + Schroeppel4 ) ^ Schroeppel4 ). toString ( 4 ); }Operaciones aritméticas
A continuación se describen las operaciones aritméticas para el sistema negabinario; los cálculos en bases más grandes son similares.
Suma
La suma de números negabinarios se realiza bit a bit, comenzando por los bits menos significativos ; los bits de cada sumando se suman con el acarreo ( ternario balanceado ) del bit anterior (0 en el LSB). Esta suma se descompone en un bit de salida y un acarreo para la siguiente iteración, como se muestra en la tabla:
La segunda fila de esta tabla, por ejemplo, expresa el hecho de que −1 = 1 + 1 × −2; la quinta fila dice 2 = 0 + −1 × −2; etc.
Como ejemplo, para sumar 1010101 −2 (1 + 4 + 16 + 64 = 85) y 1110100 −2 (4 + 16 − 32 + 64 = 52),
Acarreo: 1 −1 0 −1 1 −1 0 0 0 Primer sumando: 1 0 1 0 1 0 1 Segundo sumando: 1 1 1 0 1 0 0 + -------------------------- Número: 1 −1 2 0 3 −1 2 0 1 Bit (resultado): 1 1 0 0 1 1 0 0 1 Acarreo: 0 1 −1 0 −1 1 −1 0 0
por lo tanto el resultado es 110011001 −2 (1 − 8 + 16 − 128 + 256 = 137).
Otro método
Al sumar dos números negabinarios, cada vez que se genera un acarreo, se debe propagar un acarreo adicional al siguiente bit. Considere el mismo ejemplo anterior.
Carga adicional: 1 1 1 0 1 0 0 0 Acarreo: 0 1 1 0 1 0 0 0 Primer sumando: 1 0 1 0 1 0 1 Segundo sumando: 1 1 1 0 1 0 0 + -------------------------- Respuesta: 1 1 0 0 1 1 0 0 1
Sumador completo negabinario
Se puede diseñar un circuito sumador completo para sumar números en negabinario. La siguiente lógica se utiliza para calcular la suma y los acarreos: [ 9 ]
Incremento de números negabinarios
El incremento de un número negabinario se puede realizar utilizando la siguiente fórmula: [ 10 ]
(Las operaciones en esta fórmula deben interpretarse como operaciones sobre números binarios regulares. Por ejemplo,es un desplazamiento binario a la izquierda de un bit.)
Sustracción
Para restar, multiplica cada bit del segundo número por −1 y suma los números, utilizando la misma tabla que se muestra arriba.
Como ejemplo, para calcular 1101001 −2 (1 − 8 − 32 + 64 = 25) menos 1110100 −2 (4 + 16 − 32 + 64 = 52),
Acarreo: 0 1 −1 1 0 0 0 Primer número: 1 1 0 1 0 0 1 Segundo número: −1 −1 −1 0 −1 0 0 + -------------------- Número: 0 1 −2 2 −1 0 1 Bit (resultado): 0 1 0 0 1 0 1 Acarreo: 0 0 1 −1 1 0 0
por lo tanto el resultado es 100101 −2 (1 + 4 −32 = −27).
La negación unaria, − x , se puede calcular como una resta binaria de cero, 0 − x .
Multiplicación y división
Desplazarse hacia la izquierda multiplica por −2, desplazarse hacia la derecha divide por −2.
Para multiplicar, multiplique como si fueran números decimales o binarios normales , pero usando las reglas de los números negabinarios para agregar el acarreo al sumar los números.
Primer número: 1 1 1 0 1 1 0 Segundo número: 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 + ------------------------------------- Acarreo: 0 −1 0 −1 −1 −1 −1 −1 0 −1 0 0 Número: 1 0 2 1 2 2 2 3 2 0 2 1 0 Bit (resultado): 1 0 0 1 0 0 0 1 0 0 0 1 0 Acarreo: 0 −1 0 −1 −1 −1 −1 −1 0 −1 0 0
Para cada columna, suma el acarreo al número y divide la suma por −2 para obtener el nuevo acarreo y el bit resultante como resto.
Comparación de números negabinarios
Es posible comparar números negabinarios ajustando ligeramente un comparador binario sin signo normal . Al comparar los númerosy, invierte cada bit en posición impar de ambos números. Después de esto, comparayutilizando un comparador estándar sin signo. [ 11 ]
Números fraccionarios
La representación en base r puede, por supuesto, extenderse más allá del punto de base , lo que permite la representación de números no enteros.
Al igual que en los sistemas de base positiva, las representaciones terminantes corresponden a fracciones cuyo denominador es una potencia de la base; las representaciones repetitivas corresponden a otros números racionales, y por la misma razón.
Representaciones no únicas
A diferencia de los sistemas de base positiva, donde los enteros y las fracciones finitas tienen representaciones no únicas (por ejemplo, en decimal 0.999... = 1 ), en los sistemas de base negativa los enteros tienen una sola representación. Sin embargo, existen racionales con representaciones no únicas. Para los dígitos {0, 1, ..., t } con :=r-1=-b-1} el dígito más grande y
tenemos
- así como
Así que cada númerocon una fracción terminanteañadido tiene dos representaciones distintas.
Por ejemplo, en negaternario, es deciry, hay
- .
Tales representaciones no únicas se pueden encontrar considerando las representaciones posibles más grandes y más pequeñas con partes enteras 0 y 1 respectivamente, y luego observando que son iguales. (De hecho, esto funciona con cualquier sistema de base entera). Los racionales que se pueden expresar de forma no única son aquellos de la forma
con
Base imaginaria
Así como el uso de una base negativa permite la representación de números negativos sin un signo negativo explícito, el uso de una base imaginaria permite la representación de enteros gaussianos . Donald Knuth propuso la base cuarto-imaginaria (base 2i) en 1955. [ 12 ]
Véase también
Referencias
- ↑ Knuth, Donald (1998), El arte de la programación informática , Volumen 2 (3.ª ed.), págs. 204–205 Knuth menciona tanto el sistema negabinario como el negadecimal.
- ↑ El sistema negaternario se analiza brevemente en Petkovšek, Marko (1990), "Los números ambiguos son densos", The American Mathematical Monthly , 97 (5): 408– 411, doi : 10.2307/2324393 , ISSN 0002-9890 , JSTOR 2324393 , MR 1048915
- ↑ Vittorio Grünwald. Intorno all'aritmetica dei sistemi numerici a base negativa con particolare riguardo al sistema numerico a base negativo-decimale per lo studio delle sue analogie coll'aritmetica ordinaria (decimale), Giornale di Matematiche di Battaglini (1885), 203-221, 367
- ↑ Kempner, AJ (1936), "Sistemas anormales de numeración", American Mathematical Monthly , 43 (10): 610– 617, doi : 10.2307/2300532 , JSTOR 2300532 , MR 1523792 La única referencia a bases negativas es una nota a pie de página en la página 610, que dice: "Se pueden usar números positivos menores que 1 y números negativos como bases con ligeras modificaciones del proceso y restricciones adecuadas en el conjunto de dígitos empleados".
- ↑ Pawlak, Z.; Wakulicz, A. (1957), "Uso de expansiones con base negativa en el aritmómetro de una computadora digital", Bulletin de l'Académie Polonaise des Sciences , Classe III, 5 : 233– 236
- ↑ Marczynski, RW, "Los primeros siete años de la informática polaca" Archivado el 19 de julio de 2011 en Wayback Machine , IEEE Annals of the History of Computing, vol. 2, n.º 1, enero de 1980
- ^ "Algoritmo: documentación de zfp 1.0.1" . zfp.readthedocs.io .
- ↑ Consulte el enlace de MathWorld Negabinary. En concreto, las referencias son:
- Szudzik, M. "Desafío de programación: un concurso de programación en Mathematica". Conferencia de Tecnología Wolfram, 1999.
- Schroeppel, R. Artículo 128 en Beeler, M.; Gosper, RW; y Schroeppel, R. HAKMEM . Cambridge, MA: Laboratorio de Inteligencia Artificial del MIT, Memorando AIM-239, pág. 24, febrero de 1972. http://www.hakmem.org/#item128
- ^ Francisco, Yu; Suganda, Jutamulia; Shizuhuo, Yin (4 de septiembre de 2001). Introducción a la Óptica de la Información . Prensa académica. pag. 498.ISBN 9780127748115.
- ↑ "¿Por qué la siguiente fórmula incrementa un número negabinario (número en base −2)?" . Consultado el 29 de agosto de 2016 .
- ^ Murugesan, San (1977). "Circuitos aritméticos negativos utilizando aritmética binaria". Revista IEE sobre circuitos y sistemas electrónicos . 1 (2): 77. doi : 10.1049/ij-ecs.1977.0005 .
- ↑ D. Knuth. El arte de la programación informática. Volumen 2, 3.ª edición. Addison-Wesley. págs. 205, "Sistemas de numeración posicional".
Lecturas adicionales
- Warren Jr., Henry S. (2013) [2002]. Hacker's Delight (2.ª ed.). Addison Wesley – Pearson Education, Inc. ISBN 978-0-321-84268-8. 0-321-84268-5.
Enlaces externos
- Weisstein, Eric W. "Negabinario" . MathWorld .
- Weisstein, Eric W. "Negadecimal" . MundoMatemático .
- Sistemas de numeración posicional no estándar
- aritmética informática