¿Hay números que no son representables en la base 10 pero que se pueden representar en la base 2?

42

C#tiene el decimaltipo que se usa para los números que necesitan una representación exacta en la base 10. Por ejemplo, 0.1no se puede representar en la base 2 (por ejemplo, floaty double) y siempre será una aproximación cuando se almacena en variables que son de estos tipos.

Me preguntaba si el hecho inverso también era posible. ¿Hay números que no son representables en la base 10 pero que se pueden representar en la base 2 (en cuyo caso me gustaría usar un en floatlugar de un decimalpara manejarlos)?

Max
fuente
14
+1 a la pregunta, pero ¿es realmente aplicable la etiqueta c # aquí? Otros idiomas también tienen el tipo decimal.
Patrick M
1
@Max: Como ejercicio, te sugiero que imagines convertir un número de base 2 a base 10 a mano. Por ejemplo, para calcular el valor de 0.11_b2, escríbelo como 0.5 + 0.5 * 0.5. ¿Hay algún paso que pueda fallar o dar como resultado un decimal repetido? Personalmente, encuentro que este ejercicio hace un gran trabajo al transmitir una intuición sobre los números de base 2. Supongo que uno podría ir un paso más allá y convertir este ejercicio en una prueba por construcción.
Brian
Ah, pero te equivocas. 1/1010
Xavier J
3
@Ramhound Dadas las limitaciones de memoria, el binario puede representar 0.0999999....998..exactamente, pero no el número completo 0.1; las aproximaciones como redondear al centésimo más cercano 0.100son un problema de implementación que implica no mostrarle todos los dígitos y redondearlo.
Izkata
1
Bueno, es posible crear un mecanismo de codificación FP que permita que '0.1' se represente exactamente. Tal codificación simplemente cambia alrededor de los conjuntos de rangos de números FP que pueden y no pueden representarse.
Martin James

Respuestas:

104

Aquí está la clave de su dilema: 10es el producto de 2y 5. Puede representar cualquier número exactamente en la base 10 decimales que es k * 1/2 n * 1/5 m , donde k, ny mson números enteros.

Alternativamente redactado: si el número nen 1 / n contiene un factor que no es parte de los factores de la base, el número no podrá representarse exactamente en un número fijo de dígitos en el binario / decimal / cualquier expansión de ese número: tendrá una parte repetida. Por ejemplo 1/15 = 0.0666666666 .... porque 3 (15 = 3 * 5) no es un factor de 10.

Por lo tanto, cualquier cosa que pueda representarse exactamente en la base 2 (k * 1/2 n ) puede representarse exactamente en la base 10.

Más allá de eso, está la cuestión de cuántos dígitos / bits está utilizando para representar el número. Hay algunos números que pueden representarse exactamente en alguna base, pero se necesitan más de un número de dígitos / bits para hacerlo.


En binario, el número 1/10 que es convenientemente 0.1 en decimal no puede representarse como un número que puede representarse en un número fijo de bits en binario. En cambio, el número es 0.00011001100110011 ... 2 (con la parte 0011 repitiéndose para siempre).

Veamos el número 1 2 /1010 2 un poco más de cerca.

          ____                  
       0.00011                  
     + ---------                 
1010 | 1.00000                  
       0 0                        
       -                       
       1 0                      
         0 0                      
       ----                     
       1 00 --------- +          
          0 |          
       ----- |          
       1 000 |          
           0 |          
       ------ | repitiendo
       1 0000 | bloquear    
         1010 |          
       ------ |          
          1100 |          
          1010 |          
          ---- |          
            100 ---- +          

Este es exactamente el mismo tipo de cosas que obtienes cuando intentas hacer la división larga para 1/3.

1/10, cuando se factoriza es 1 / (2 1 * 5 1 ). Para la base 10 (o cualquier múltiplo de 10), este número termina y se conoce como un número regular . Una expansión decimal que se repite se conoce como decimal decimal , y los números que continúan para siempre sin repetirse son números irracionales.

La matemática detrás de esta ahonda en el pequeño teorema de Fermat ... y una vez que empieza a decir Fermat o teorema, se convierte en una cuestión Math.SE .

¿Hay números que no son representables en la base 10 pero que se pueden representar en la base 2?

La respuesta es no'.

Entonces, en este punto, todos deberíamos tener claro que cada expansión binaria de longitud fija de un número racional puede representarse como una expansión decimal de longitud fija.


Veamos más de cerca el decimal en C # que nos lleva al punto flotante decimal en .NET y dado el autor, aceptaré que así es como funciona.

El tipo decimal tiene los mismos componentes que cualquier otro número de coma flotante: una mantisa, un exponente y un signo. Como de costumbre, el signo es solo un bit, pero hay 96 bits de mantisa y 5 bits de exponente. Sin embargo, no todas las combinaciones de exponentes son válidas. Solo los valores del 0 al 28 funcionan, y son efectivamente todos negativos: el valor numérico es . Esto significa que los valores máximos y mínimos del tipo son +/- (2 96 -1), y el número más pequeño que no es cero en términos de magnitud absoluta es 10-28 .sign * mantissa / 10exponent

Señalaré de inmediato que, debido a esta implementación, hay números en el doubletipo que no se pueden representar decimal, aquellos que están fuera del rango. Double.Epsilones lo 4.94065645841247e-324que no puede representarse en a decimal, pero puede en a double.

Sin embargo, dentro del rango que puede representar el decimal, tiene más bits de precisión que otros tipos nativos y puede representarlos sin error.

Hay algunos otros tipos flotando. Hay un BigInteger en C # que puede representar un entero arbitrariamente grande. No hay equivalente al BigDecimal de Java (que puede representar números con dígitos decimales de hasta 2 32 dígitos de largo, que es un rango considerable) exactamente . Sin embargo, si hurgas un poco , puedes encontrar implementaciones enrolladas a mano.

Hay algunos lenguajes que también tienen un tipo de datos racional que le permite representar exactamente los racionales (de modo que 1/3 es en realidad 1/3).


Específicamente para C # y la elección de flotante o racional, diferiré a Jon Skeet de la pinta flotante Decimal en .NET :

La mayoría de las aplicaciones comerciales probablemente deberían estar usando decimal en lugar de flotante o doble. Mi regla general es que los valores hechos por el hombre, como la moneda, generalmente se representan mejor con coma flotante decimal: el concepto de exactamente 1,25 dólares es completamente razonable, por ejemplo. Para valores del mundo natural, como longitudes y pesos, los tipos de punto flotante binario tienen más sentido. A pesar de que existe un "exactamente 1,25 metros" teórico, nunca va a ocurrir en la realidad: ciertamente nunca podrá medir longitudes exactas, y es poco probable que existan incluso a nivel atómico. Estamos acostumbrados a que haya cierta tolerancia involucrada.

Comunidad
fuente
+1 para una explicación matemática clara y concisa. Y para responder a la versión más general de la pregunta planteada en el título, un ejemplo de un número no representable en la base 10 es 1/3.
Doval
@Doval Sospecho que hay un error en mi razonamiento o explicación que una persona más orientada a las matemáticas podría señalar ... pero creo que estoy en el camino correcto si ese es el caso.
"Relativamente primo" en este caso solo significa "no es un factor de", ¿verdad? ¿Hay alguna relación matemática más profunda que me falta?
Patrick M
1
Ah, por lo que entiendo, n = 15y b = 10no son relativamente primos ("no comparten factores positivos comunes (divisores) excepto 1") porque comparten 5 como factor. La clave es que no todos los factores de 15 (5 y 3) no son también factores de 10. (Aparte: ¿hay una palabra para indicar números que comparten o no todos los factores comunes?) Creo que eso es claramente envuelto en su k, n, mecuación, pero para entenderlo realmente, necesitaría ver un diagrama en 3D. En cualquier caso, bien merecido +1 para ti.
Patrick M
1
@PatrickM: "Aparte: ¿hay una palabra para indicar números que comparten o no todos los factores comunes?": Cualquier número entero es un factor en sí mismo, por lo que si todos los factores de m son factores de n , entonces trivialmente se deduce que m es un factor de n . Un término para esto, como saben claramente, es factor . Otro es el divisor .
ruakh
6

Una vez que salga del rango de valores aceptables, la respuesta es sí. Dicho esto, casi cualquier cosa dentro del rango tendrá una representación. C # Referencia decimal Aunque no se indica en la especificación, los números irracionales no se pueden representar con exactitud (p. Ej., E 1 , pi, raíz cuadrada de 2, etc.).

La palabra clave decimal denota un tipo de datos de 128 bits. En comparación con los tipos de coma flotante, el tipo decimal tiene una mayor precisión y un rango más pequeño, lo que lo hace adecuado para cálculos financieros y monetarios. El rango aproximado y la precisión para el tipo decimal se muestran en la siguiente tabla.

Precisión: 28-29 dígitos significativos

1 Gracias a MichaelT por recordarme otro número irracional.

Adam Zuckerman
fuente
2
@Magus considera el número irracional e(2.71 ...). El log natural - ln (x) es log base e. Por lo tanto, existen bases irracionales y son útiles. No estoy seguro de la utilidad particular de la base pi, pero eso no significa que no se use en alguna parte.
66
@Max, te estás desviando cada vez más en las preguntas de matemáticas. Puede encontrar Si un número es irracional en la base 10, ¿es irracional en otras bases? ser una lectura útil y un punto de partida para más preguntas de teoría de números.
2
1/3 no es irracional.
Adam Zuckerman
2
El OP preguntó sobre la base 10 (diez). Hacer una base del sistema numérico de cualquier cosa le permitirá expresar cualquier cosa como 10. Según el artículo de Wikipedia , usar un número irracional como base no lo hace racional. Los números racionales se pueden expresar como enteros tanto para el numerador como para el denominador, repitiendo números en un decimal o terminación finita de números en un decimal.
Adam Zuckerman
55
@FrustratedWithFormsDesigner La irracionalidad no tiene nada que ver con las bases. Bueno, eso es una exageración, pero es la irracionalidad lo que tiene implicaciones para la representación del número en varias bases (por ejemplo, si tiene infinitos dígitos que no se repiten), y no al revés. Lea la pregunta de math.se vinculada a la anterior: math.stackexchange.com/questions/625473/…
1

Un tipo de punto flotante de base dos podría representar con precisión muchos valores que no podría un tipo de base diez del mismo tamaño . Cualquier valor que sería exactamente representable por un tipo base-2 de algún tamaño sería exactamente representable en un tipo base-diez de tamaño suficiente. El tamaño requerido para un tipo de base puramente diez para representar todos los valores de un número de punto flotante binario dependería del rango de exponente del tipo binario; cientos de bits por a float, o miles por a double.

Dicho esto, el Decimaltipo es lo suficientemente grande como para que hubiera sido posible utilizarlo como un tipo "universal" capaz de mantener el valor de cualquier otra primitiva numérica y proporcionar otras características adicionales además (si nada más, use un bit para indicar si el valor almacenado es el resultado de convertir a double, y si ese bit está establecido, use 64 bits para mantener el valor en cuestión). Microsoft optó por no hacer eso, sin embargo. Como resultado, la conversión de doublea Decimalfallará por completo para valores grandes, hará que los valores pequeños se redondeen al 1E-28 más cercano. Además, incluso dentro del rango dinámico dedecimal, el método de conversión no será "ida y vuelta". Por ejemplo, evaluar 1.0 / 3.0 como doble producirá 0.3333333333333333148, pero convertir eso a decimal generará 0.333333333333333m y convertir eso nuevamente a doble produciría 0.3333333333333329818.

Super gato
fuente