2009-09-17 6 views
9

? Para una computadora que trabaja con un procesador de 64 bits, el número más grande que puede manejar sería 2 = 18,446,744,073,709,551,616. ¿Cómo maneja los lenguajes de programación, por ejemplo Java o C, C++, la aritmética de números superiores a este valor? Cualquier registro no puede contenerlo como una sola pieza. ¿Cómo se abordó este tema?¿Cómo manejan los lenguajes de programación la aritmética de números enormes

+0

¿Se trata de una pregunta sobre enteros grandes o sobre cómo se representan los números de coma flotante grandes? – mob

+0

Enteros simplemente para obtener el concepto correcto por ahora :) – Ajay

+2

Hice una pregunta similar y finalmente encontré mi camino aquí; http://stackoverflow.com/questions/1218149/arbitrary-precision-arithmetic-explanation/1218185#1218185 ¡Buena caza! – deau

Respuesta

0

En general, el lenguaje mismo no maneja de alta precisión, de alta precisión gran número aritmética. Es mucho más probable que se escriba una biblioteca que utiliza métodos numéricos alternativos para realizar las operaciones deseadas.

Por ejemplo (sólo estoy haciendo esto ahora mismo), tal biblioteca podría emular las técnicas actuales que puede utilizar para llevar a cabo esa gran aritmética de números con la mano. Dichas bibliotecas generalmente son mucho más lentas que con la aritmética incorporada, pero en ocasiones se requiere precisión y precisión adicional.

+0

Ok, como sea, cuando se trata de operaciones aritméticas, digamos que al sumar los dos números grandes, ambos deben estar en registros, para los cuales el tamaño del registro no es suficiente. ¿Cómo se aborda este problema? – Ajay

+0

Puede realizar una única operación aritmética de gran tamaño realizando muchas más pequeñas. Creo que lo dije con bastante claridad en el segundo párrafo ... –

+0

No agrega 123098712380714091823 a 120497235897345089273403 en una hoja de papel a la vez, ¿o sí? Realiza muchas operaciones más pequeñas, una a la vez. –

0

Supongo que es incorrecto. El número más grande que puede manejar en un solo registro es un número de 64 bits. Sin embargo, con algunas técnicas de programación inteligente, podría simplemente combinar algunas docenas de esos números de 64 bits en una fila para generar un gran número de 6400 bits y usar eso para hacer más cálculos. Simplemente no es tan rápido como tener el número en un registro.

Incluso los viejos procesadores de 8 y 16 bits utilizado este truco, donde serían simplemente dejar que el desbordamiento de número a otros registros. Hace que las matemáticas sean más complejas, pero no pone fin a las posibilidades.

Sin embargo, estas matemáticas de alta precisión son extremadamente inusuales. Incluso si quiere calcular la deuda nacional total de los EE. UU. Y almacenar el resultado en dólares zimbabuenses, un número entero de 64 bits todavía sería lo suficientemente grande, creo. Sin embargo, definitivamente es lo suficientemente grande como para contener el monto de mi cuenta de ahorros.

+0

no es verdad ... Es especialmente la parte fraccionaria que no quieren redondear a rápido (por ejemplo, cuando se usan números de coma flotante normales) – Toad

+0

@reinier, Donald Knuth ha escrito varios buenos libros y artículos sobre este tema y computadoras y matemáticas en general. Sugiero que comiences a leer algunos de esos. Muchos idiomas tienen una biblioteca BigNum especial, que se puede implementar de muchas maneras. (Ver http://en.wikipedia.org/wiki/Bignum) –

+0

No es inusual ... mmm qué tal ... digamos que quiero 35! .. que cruza el límite fácilmente – Ajay

0

Como experimento mental, imagina los números almacenados como una cadena. Con funciones para agregar, multiplicar, etc. estos números arbitrariamente largos.

En realidad, estos números son probablemente almacenan en un espacio de manera más eficiente.

0

pensar en un número de máquina de tamaño como un dígito y aplicar el algoritmo para la multiplicación de varios dígitos de la escuela primaria. Entonces no necesita mantener los números enteros en registros, solo los dígitos mientras se trabajan.

5

Hay un montón de técnicas especializadas para hacer cálculos en números más grandes que el tamaño de registro. Algunos de ellos se describen en este artículo de la wikipedia en arbitrary precision arithmetic

Los idiomas de bajo nivel, como C y C++, dejan cálculos de números grandes a la biblioteca de su elección. Uno notable es el GNU Multi-Precision library. Los lenguajes de alto nivel, como Python, y otros, integran esto en el núcleo del lenguaje, por lo que los números normales y los números muy grandes son idénticos al programador.

0

La mayoría de los idiomas los almacena como una matriz de números enteros. Si suma/resta dos de estos números grandes, la biblioteca agrega/resta todos los elementos enteros del conjunto por separado y maneja los acarreos/préstamos. Es como la suma/resta manual en la escuela porque así es como funciona internamente.

Algunos lenguajes utilizan cadenas de texto reales en lugar de matrices enteras, lo que es menos eficiente pero más simple de transformar en representación de texto.

1

Ada en realidad lo admite de forma nativa, pero solo para sus constantes sin tipo ("números con nombre"). Para las variables reales, debe buscar un paquete de longitud arbitraria. Ver Arbitrary length integer in Ada

+0

+1 Interesante verte en SO, [TED ] (http://stackoverflow.com/users/29639/ted) –

+0

Me di cuenta de que Ada lo soportaba como un built-in, leyendo en otro lugar, pero no sabía que estaba limitado a las constantes. Eso es un poco extraño. ¿Puedes incluso tomar un bignum constante + una pequeña int, y terminar con un resultado bignum? –

1

Más o menos de la misma manera que que haces. En la escuela, memorizaste suma, multiplicación, sustracción y división de un solo dígito. Luego, aprendió cómo hacer problemas de varios dígitos como una secuencia de problemas de un solo dígito.

Si lo desea, puede multiplicar dos números de veinte dígitos juntos utilizando nada más que el conocimiento de un algoritmo simple y las tablas de multiplicar de un solo dígito.

+0

Eso es cierto, hasta donde llega. Sin embargo, solo hace lo básico: suma, resta, multiplicación y división son solo el comienzo. Entonces, para realmente a los números arbitrarios, debe preocuparse por las raíces cuadradas, el seguimiento de precisión, etc. Es por eso que creo que cada lenguaje debe proporcionar una implementación buena y completa como estándar. –

0

Los lenguajes de programación que manejan números verdaderamente masivos usan primitivas de números personalizados que van más allá de las operaciones normales optimizadas para CPU de 32, 64 o 128 bits. Estos números son especialmente útiles en la seguridad informática y la investigación matemática.

El GNU Multiple Precision Library es probablemente el ejemplo más completo de estos enfoques.

Puede manejar números más grandes mediante el uso de matrices. Pruébelo en su navegador web. Escriba el siguiente código en la consola JavaScript de su navegador web:

El punto en el que JavaScript no

console.log(9999999999999998 + 1) 
// expected 9999999999999999 
// actual 10000000000000000 oops! 

JavaScript no maneja enteros normales por encima de 9999999999999998. Pero escribir tu propio número primitivo es hacer que este cálculo funcione es bastante simple. Aquí hay un ejemplo usando a custom number adder class in JavaScript.

Al pasar la prueba usando una clase de número personalizado

// Require a custom number primative class 
const {Num} = require('./bases') 

// Create a massive number that JavaScript will not add to (correctly) 
const num = new Num(9999999999999998, 10) 

// Add to the massive number 
num.add(1) 

// The result is correct (where plain JavaScript Math would fail) 
console.log(num.val) // 9999999999999999 

Cómo funciona

Usted puede mirar en el código en class Num { ... } para ver los detalles de lo que está sucediendo; pero aquí es un esquema básico de la lógica en uso:

Clases:

  • La clase Num contiene un conjunto de clases individuales Digit.
  • La clase Digit contiene el valor de un solo dígito, y la lógica para manejar los Carry flag

Pasos:

  1. El número elegido se convierte en una cadena
  2. se gira Cada dígito en una clase Digit y almacenada en la clase Num como una matriz de dígitos
  3. Cuando se incrementa el Num, se lleva a cabo o la primera Digit en la matriz (la más a la derecha número)
  4. Si el valor Digit más la Carry flag son iguales a la Base, entonces el siguiente Digit a la izquierda está llamada a ser incrementado, y el número actual se pone a 0
  5. ... Repetir todo el camino hasta el dígito más a la izquierda de la matriz

Logísticamente es muy similar a lo que sucede en el nivel de la máquina, pero aquí es ilimitada. Puede read more about about how digits are carried here; esto se puede aplicar a los números de cualquier base.

Cuestiones relacionadas