Estaba leyendo un artículo de Microsoft sobre Ampliación de conversiones y Opción estrictamente activada cuando llegué a la parte
Las siguientes conversiones pueden perder precisión:
- Integer a Single
- Largo a simple o doble
- Decimal a simple o doble
Sin embargo, estas conversiones no pierden información o magnitud.
.. pero de acuerdo con otro artículo sobre tipos de datos ,
El tipo entero puede almacenar de -2.147.483.648 a 2.147.483.647 y
Solo tipo puede almacenar desde
- 1,401298E-45 a 3,4028235E + 38 para números positivos,
- y -3,4028235E + 38 a - 1,401298E-45 para números negativos
.. entonces Single puede almacenar muchos más números que Integer. No podía entender en qué situación tal conversión de Integer a Single puede perder precisión. ¿Podría alguien explicarme, por favor?
fuente
Integer
s (99,2%) no se pueden representar comoSingle
, por lo que "cuando" es "casi siempre".Single
solo puedes representar 4,278,190,079 números diferentes. UnSingle
valor representa un número si y solo si el exponente almacenado no es 255, lo que significa que hay 255 * 2 ^ 24Single
s que representan números. De estos, dos de ellos representan el mismo número (a saber, cero), y los otros representan números diferentes.[-16777216,16777216]
(2 ^ 24 = el ancho significativo) se pueden representar exactamente. Los números más grandes se redondean al múltiplo más cercano de 2, 4, 8, ... dependiendo de qué tan grandes sean.Single
tiene dos formas de almacenar cero. EntoncesSingle
, de hecho, puede representar menos números distintos queInteger
.Los tipos de punto flotante (como Single y Double) se representan en la memoria mediante un signo, una mantisa y un exponente. Piense en ello como notación científica:
Ellos, como es de esperar, usan la base 2. Hay otros ajustes que permiten representar el infinito y NaN, y el exponente está compensado (volverá a eso), y una abreviatura de la mantisa (volverá a eso también) . Busque el estándar IEEE 754 que cubre su representación y operaciones para obtener más detalles.
Para nuestros propósitos, podemos imaginarlo como un número binario "mantissa" y un "exponente" que le dice dónde colocar el separador decimal.
En el caso de Single, tenemos 1 bit para el signo, 8 para el exponente y 23 para la mantisa.
Ahora, la cosa es que almacenaremos la mantisa desde el dígito más significativo. Recuerde que todos los ceros a la izquierda no son relevantes. Y dado que estamos trabajando en binario, sabemos que el dígito más significativo es un 1 ※. Bueno, como sabemos eso, no tenemos que almacenarlo. Gracias a esa taquigrafía, el rango efectivo de la mantisa es de 24 bits.
※: A menos que el número que estamos almacenando sea cero. Para eso tendremos todos los bits puestos a cero. Sin embargo, si intentamos interpretar eso bajo la descripción que di, tendrías un 2 ^ 24 (el implícito 1) multiplicado por 1 (2 a la potencia del exponente 0). Entonces, para arreglarlo, el exponente cero es un valor especial. También hay valores especiales para almacenar infinito y NaN en el exponente.
Según el desplazamiento del exponente, además de evitar los valores especiales, tenerlo desplazado permite colocar el punto decimal antes del comienzo de la mantisa o después de su final, sin la necesidad de tener un signo para el exponente.
Esto significa que para números grandes, el tipo de coma flotante colocará el punto decimal más allá del final de la mantisa.
Recuerde que la mantisa es un número de 24 bits. Nunca representará un número de 25 bits ... no tiene ese bit extra. Por lo tanto, el single no puede distinguir entre 2 ^ 24 y 2 ^ 24 + 1 (estos son los primeros números de 25 bits, y difieren en el último bit, que no está representado en el single).
Por lo tanto, para enteros, el rango del single es -2 ^ 24 a 2 ^ 24. E intentar agregar 1 a 2 ^ 24 dará como resultado 2 ^ 24 (porque en lo que respecta al tipo, 2 ^ 24 y 2 ^ 24 + 1 son el mismo valor). Pruébalo en línea . Es por eso que hay una pérdida de información al convertir de entero a único. Y esta es también la razón por la cual un bucle que usa un simple o doble podría ser un bucle infinito sin que lo notes.
fuente
1
bit inicial implícito en el significado. Está implícito en que el campo de exponente sesgado no es cero . Los subnormales (también conocidos como denormales) incluyen+-0.0
una parte importante0
de su significado. Supongo que podría simplificarse para considerar0.0
un caso totalmente especial, pero en0.0
realidad sigue las mismas reglas de codificación que otros subnormales.Aquí hay un ejemplo real de cuando la conversión de
Integer
aSingle
puede perder precisión:El
Single
tipo puede almacenar todos los enteros desde -16777216 hasta 16777216 (inclusive), pero no puede almacenar todos los enteros fuera de este rango. Por ejemplo, no puede almacenar el número 16777217. Por lo demás, no puede almacenar ningún número impar mayor que 16777216.Podemos usar Windows PowerShell para ver qué sucede si convertimos an
Integer
en aySingle
viceversa:Observe que 16777217 se redondeó a 16777216 y 16777219 se redondeó a 16777220.
fuente
float
sigue creciendo como potencias de. en.wikipedia.org/wiki/…Los tipos de punto flotante son similares a la "notación científica" en física. El número se divide en un bit de signo, un exponente (multiplicador) y una mantisa (dígitos significativos). Entonces, a medida que aumenta la magnitud del valor, también aumenta el tamaño del paso.
El punto flotante de precisión simple tiene 23 bits de mantisa, pero hay un "1 implícito", por lo que la mantisa es efectivamente de 24 bits. Por lo tanto, todos los enteros con una magnitud de hasta 2 24 se pueden representar exactamente en coma flotante de precisión simple.
Por encima de eso, sucesivamente se pueden representar menos números.
Entonces, de los 2 32 posibles valores enteros con signo de 32 bits, solo 2 * (2 24 + 7 * 2 23 ) = 9 * 2 24 se pueden representar en coma flotante de precisión simple. Eso es 3.515625% del total.
fuente
Los flotadores de precisión simple tienen 24 bits de precisión. Cualquier cosa sobre eso se redondea al número de 24 bits más cercano. Puede ser más fácil de entender en notación científica decimal, pero tenga en cuenta que los flotadores reales usan binario.
Digamos que tiene 5 dígitos decimales de memoria. Puede elegir usarlos como un int sin signo regular, lo que le permite tener cualquier número entre 0 y 99999. Si desea poder representar números más grandes, puede usar notación científica y simplemente asignar dos dígitos para ser el exponente, por lo que ahora puede representar cualquier cosa entre 0 y 9.99 x 10 99 .
Sin embargo, el número más grande que puede representar exactamente ahora es solo 999. Si intentó representar 12345, puede obtener 1.23 x 10 4 , o 1.24 x 10 4 , pero no puede representar ninguno de los números intermedios, porque no tiene suficientes dígitos disponibles.
fuente