stringtranslate.com

Peso Hamming

El peso Hamming de una cadena es el número de símbolos que son diferentes del símbolo cero del alfabeto utilizado. Por tanto, es equivalente a la distancia de Hamming desde la cuerda totalmente cero de la misma longitud. Para el caso más típico, una cadena de bits , este es el número de unos en la cadena, o la suma de dígitos de la representación binaria de un número dado y la norma ℓ ₁ de un vector de bits. En este caso binario, también se le llama recuento de población , [1] popcount , suma lateral , [2] o suma de bits . [3]

Historia y uso

El peso Hamming lleva el nombre de Richard Hamming , aunque no fue él quien originó la idea. [7] El peso de Hamming de los números binarios ya fue utilizado en 1899 por James WL Glaisher para dar una fórmula para el número de coeficientes binomiales impares en una sola fila del triángulo de Pascal . [8] Irving S. Reed introdujo un concepto equivalente al peso de Hamming en el caso binario, en 1954. [9]

El peso de Hamming se utiliza en varias disciplinas, incluidas la teoría de la información , la teoría de la codificación y la criptografía . Ejemplos de aplicaciones del peso Hamming incluyen:

Implementación eficiente

El recuento de población de una cadena de bits suele ser necesario en criptografía y otras aplicaciones. La distancia de Hamming de dos palabras A y B se puede calcular como el peso de Hamming de A x o B. [1]

El problema de cómo implementarlo eficientemente ha sido ampliamente estudiado. En algunos procesadores está disponible una sola operación para el cálculo u operaciones paralelas sobre vectores de bits. Para los procesadores que carecen de esas características, las mejores soluciones conocidas se basan en sumar recuentos en un patrón de árbol. Por ejemplo, para contar el número de bits 1 en el número binario de 16 bits a = 0110 1100 1011 1010, se pueden realizar estas operaciones:

Aquí, las operaciones son como en el lenguaje de programación C , por lo que X >> Ysignifica desplazar X hacia la derecha en Y bits, X e Y significa el AND bit a bit de X e Y, y + es una suma ordinaria. Los mejores algoritmos conocidos para este problema se basan en el concepto ilustrado anteriormente y se detallan aquí: [1]

//tipos y constantes utilizados en las funciones siguientes //uint64_t es un tipo de variable entero de 64 bits sin signo (definido en la versión C99 del lenguaje C) const uint64_t m1 = 0x5555555555555555 ; //binario: 0101... const uint64_t m2 = 0x3333333333333333 ; //binario: 00110011.. const uint64_t m4 = 0x0f0f0f0f0f0f0f0f ; //binario: 4 ceros, 4 unos... const uint64_t m8 = 0x00ff00ff00ff00ff ; //binario: 8 ceros, 8 unos... const uint64_t m16 = 0x0000ffff0000ffff ; //binario: 16 ceros, 16 unos... const uint64_t m32 = 0x00000000ffffffff ; //binario: 32 ceros, 32 unos const uint64_t h01 = 0x0101010101010101 ; //la suma de 256 elevado a 0,1,2,3...                                   //Esta es una implementación ingenua, que se muestra para comparar //y para ayudar a comprender las mejores funciones. //Este algoritmo utiliza 24 operaciones aritméticas (desplazar, sumar y). int popcount64a ( uint64_t x ) { x = ( x & m1 ) + (( x >> 1 ) & m1 ); //poner el recuento de cada 2 bits en esos 2 bits x = ( x & m2 ) + (( x >> 2 ) & m2 ); //poner el recuento de cada 4 bits en esos 4 bits x = ( x & m4 ) + (( x >> 4 ) & m4 ); //poner el recuento de cada 8 bits en esos 8 bits x = ( x & m8 ) + (( x >> 8 ) & m8 ); //poner el recuento de cada 16 bits en esos 16 bits x = ( x & m16 ) + (( x >> 16 ) & m16 ); //poner el recuento de cada 32 bits en esos 32 bits x = ( x & m32 ) + (( x >> 32 ) & m32 ); //poner el recuento de cada 64 bits en esos 64 bits return x ; }                                                                                    //Esto utiliza menos operaciones aritméticas que cualquier otra //implementación conocida en máquinas con multiplicación lenta. //Este algoritmo utiliza 17 operaciones aritméticas. int popcount64b ( uint64_t x ) { x -= ( x >> 1 ) & m1 ; //poner el recuento de cada 2 bits en esos 2 bits x = ( x & m2 ) + (( x >> 2 ) & m2 ); //poner el recuento de cada 4 bits en esos 4 bits x = ( x + ( x >> 4 )) & m4 ; //poner el recuento de cada 8 bits en esos 8 bits x += x >> 8 ; //poner el recuento de cada 16 bits en sus 8 bits más bajos x += x >> 16 ; //poner el recuento de cada 32 bits en sus 8 bits más bajos x += x >> 32 ; //poner el recuento de cada 64 bits en sus 8 bits más bajos return x & 0x7f ; }                                                      //Esto utiliza menos operaciones aritméticas que cualquier otra //implementación conocida en máquinas con multiplicación rápida. //Este algoritmo utiliza 12 operaciones aritméticas, una de las cuales es una multiplicación. int popcount64c ( uint64_t x ) { x -= ( x >> 1 ) & m1 ; //poner el recuento de cada 2 bits en esos 2 bits x = ( x & m2 ) + (( x >> 2 ) & m2 ); //poner el recuento de cada 4 bits en esos 4 bits x = ( x + ( x >> 4 )) & m4 ; //poner el recuento de cada 8 bits en esos 8 bits return ( x * h01 ) >> 56 ; //devuelve los 8 bits restantes de x + (x<<8) + (x<<16) + (x<<24) + ... }                                       

Las implementaciones anteriores tienen el mejor comportamiento en el peor de los casos de cualquier algoritmo conocido. Sin embargo, cuando se espera que un valor tenga pocos bits distintos de cero, puede ser más eficiente utilizar algoritmos que cuenten estos bits uno a la vez. Como Wegner describió en 1960, [14] el AND bit a bit de x con x  − 1 difiere de x solo en poner a cero el bit distinto de cero menos significativo: restar 1 cambia la cadena de ceros más a la derecha a 1, y cambia el 1 más a la derecha a un 0 Si x originalmente tenía n bits que eran 1, entonces después de sólo n iteraciones de esta operación, x se reducirá a cero. La siguiente implementación se basa en este principio.

//Esto es mejor cuando la mayoría de los bits en x son 0 //Este algoritmo funciona igual para todos los tamaños de datos. //Este algoritmo utiliza 3 operaciones aritméticas y 1 comparación/ramificación por "1" bit en x. int popcount64d ( uint64_t x ) { int recuento ; para ( cuenta = 0 ; x ; cuenta ++ ) x &= x - 1 ; recuento de retornos ; }               

Si se permite un mayor uso de memoria, podemos calcular el peso de Hamming más rápido que los métodos anteriores. Con memoria ilimitada, podríamos simplemente crear una tabla de búsqueda grande del peso Hamming de cada entero de 64 bits. Si podemos almacenar una tabla de búsqueda de la función Hamming de cada entero de 16 bits, podemos hacer lo siguiente para calcular el peso Hamming de cada entero de 32 bits.

static uint8_t wordbits [ 65536 ] = { /* recuentos de bits de números enteros del 0 al 65535, inclusive */ }; //Este algoritmo utiliza 3 operaciones aritméticas y 2 lecturas de memoria. int popcount32e ( uint32_t x ) { devolver bits de palabras [ x & 0xFFFF ] + bits de palabras [ x >> 16 ]; }                
//Opcionalmente, la tabla wordbits[] podría completarse usando esta función int popcount32e_init ( void ) { uint32_t i ; uint16_tx ; _ recuento int ; para ( yo = 0 ; yo <= 0xFFFF ; yo ++ ) { x = yo ; for ( count = 0 ; x ; count ++ ) // tomado de popcount64d() arriba x &= x - 1 ; bits de palabras [ i ] = contar ; } }                               

Muła et al. [15] han demostrado que una versión vectorizada de popcount64b puede ejecutarse más rápido que instrucciones dedicadas (por ejemplo, popcnt en procesadores x64).

Peso mínimo

En la codificación de corrección de errores , el peso mínimo de Hamming, comúnmente conocido como peso mínimo w min de un código, es el peso de la palabra de código distinta de cero de menor peso. El peso w de una palabra de código es el número de unos en la palabra. Por ejemplo, la palabra 11001010 tiene un peso de 4.

En un código de bloque lineal, el peso mínimo es también la distancia mínima de Hamming ( d min ) y define la capacidad de corrección de errores del código. Si w min  =  n , entonces d min  =  n y el código corregirá hasta d min /2 errores. [dieciséis]

Ayuda de idioma

Algunos compiladores de C proporcionan funciones intrínsecas que proporcionan funciones de recuento de bits. Por ejemplo, GCC (desde la versión 3.4 en abril de 2004) incluye una función incorporada __builtin_popcountque utilizará una instrucción de procesador si está disponible o una implementación de biblioteca eficiente en caso contrario. [17] LLVM-GCC ha incluido esta función desde la versión 1.5 en junio de 2005. [18]

En la biblioteca estándar de C++ , la estructura de datos de matriz de bits bitsettiene un count()método que cuenta el número de bits configurados. En C++20<bit> , se agregó un nuevo encabezado que contiene funciones std::popcounty std::has_single_bit, tomando argumentos de tipos enteros sin signo.

En Java, la estructura de datos de matriz de bits ampliable BitSettiene un BitSet.cardinality()método que cuenta la cantidad de bits que se configuran. Además, existen Integer.bitCount(int)funciones Long.bitCount(long)para contar bits en enteros primitivos de 32 y 64 bits, respectivamente. Además, la BigIntegerclase entera de precisión arbitraria también tiene un BigInteger.bitCount()método que cuenta bits.

En Python , el inttipo tiene un bit_count()método para contar el número de bits establecidos. Esta funcionalidad se introdujo en Python 3.10, lanzado en octubre de 2021. [19]

En Common Lisp , la función logcount, dado un número entero no negativo, devuelve el número de 1 bits. (Para números enteros negativos, devuelve el número de bits 0 en notación en complemento a 2). En cualquier caso, el número entero puede ser BIGNUM.

A partir de GHC 7.4, el paquete base de HaskellpopCount tiene una función disponible en todos los tipos que son instancias de la Bitsclase (disponible en el Data.Bitsmódulo). [20]

La versión MySQL del lenguaje SQLBIT_COUNT() proporciona una función estándar. [21]

Fortran 2008 tiene la función elemental intrínseca estándar popcntque devuelve el número de bits distintos de cero dentro de un número entero (o matriz de enteros). [22]

Algunas calculadoras científicas de bolsillo programables cuentan con comandos especiales para calcular el número de bits configurados, por ejemplo, #Ben HP-16C [3] [23] y WP 43S , [24] [25] #BITS[26] [27] o BITSUM[28] [29 ] en emuladores HP-16C y nBITSen WP 34S . [30] [31]

FreePascal implementa popcnt desde la versión 3.0. [32]

Soporte de procesador

Ver también

Referencias

  1. ^ abcdefg Warren Jr., Henry S. (2013) [2002]. El placer del hacker (2 ed.). Addison Wesley - Pearson Education, Inc. págs. 81–96. ISBN 978-0-321-84268-8. 0-321-84268-5.
  2. ^ Knuth, Donald Ervin (2009). "Trucos y técnicas bit a bit; diagramas de decisión binaria". El arte de la programación informática . vol. 4, fascículo 1. Addison–Wesley Professional . ISBN 978-0-321-58050-4.(NB. Borrador del fascículo 1b disponible para descargar).
  3. ^ ab Manual del propietario del informático informático Hewlett-Packard HP-16C (PDF) . Compañía Hewlett-Packard . Abril de 1982. 00016-90001. Archivado (PDF) desde el original el 28 de marzo de 2017 . Consultado el 28 de marzo de 2017 .
  4. ^ [1], escrito en Fōrmulæ. La wiki de Fórmulas . Consultado el 30 de septiembre de 2019.
  5. ^ Una solución a la tarea Recuento de población. Consultado el 30 de septiembre de 2019.
  6. ^ Código Rosetta. Consultado el 30 de septiembre de 2019.
  7. ^ Thompson, Thomas M. (1983). Desde códigos de corrección de errores pasando por empaquetamientos de esferas hasta grupos simples . Las monografías matemáticas de Carus #21. La Asociación Matemática de América . pag. 33.
  8. ^ Glaisher, James Whitbread Lee (1899). "Sobre el residuo de un coeficiente del teorema binomial con respecto a un módulo primo". La revista trimestral de matemáticas puras y aplicadas . 30 : 150-156.(NB. Véase en particular el último párrafo de la pág. 156.)
  9. ^ Reed, Irving Stoy (1954). "Una clase de códigos de corrección de errores múltiples y el esquema de decodificación". Grupo Profesional IRE de Teoría de la Información . Instituto de Ingenieros de Radio (IRE). PGIT-4: 38–49.
  10. ^ Cohen, Gerard D .; Lobstein, Antoine; Naccache, David; Zémor, Gilles (1998). "Cómo mejorar una caja negra de exponenciación". En Nyberg, Kaisa (ed.). Avances en criptología - EUROCRYPT '98, Conferencia internacional sobre teoría y aplicación de técnicas criptográficas, Espoo, Finlandia, 31 de mayo - 4 de junio de 1998, Actas . Apuntes de conferencias sobre informática. vol. 1403. Saltador. págs. 211-220. doi : 10.1007/BFb0054128 .
  11. ^ Estoica, yo; Morris, R.; Liben-Nowell, D.; Karger, DR; Kaashoek, MF; Dabek, F.; Balakrishnan, H. (febrero de 2003). "Chord: un protocolo de búsqueda punto a punto escalable para aplicaciones de Internet". Transacciones IEEE/ACM en redes . 11 (1): 17–32. doi :10.1109/TNET.2002.808407. S2CID  221276912. Sección 6.3: "En general, la cantidad de dedos que debemos seguir será la cantidad de unos en la representación binaria de la distancia desde el nodo hasta la consulta".
  12. ^ ab SPARC International, Inc. (1992). «A.41: Conteo de Población. Nota de Programación» . El manual de arquitectura SPARC: versión 8 (Versión 8 ed.). Englewood Cliffs, Nueva Jersey, Estados Unidos: Prentice Hall . págs.231 . ISBN 0-13-825001-4.
  13. ^ Blaxell, David (1978). Hogben, David; Fife, Dennis W. (eds.). "Vinculación de registros mediante coincidencia de patrones de bits". Informática y estadística: Décimo simposio anual sobre la interfaz . Publicación especial de NBS. Departamento de Comercio de EE. UU./Oficina Nacional de Normas . 503 : 146-156.
  14. ^ Wegner, Peter (mayo de 1960). "Una técnica para contar unos en una computadora binaria". Comunicaciones de la ACM . 3 (5): 322.doi : 10.1145 /367236.367286 . S2CID  31683715.
  15. ^ Muła, Wojciech; Kurz, Nathan; Lemire, Daniel (enero de 2018). "Recuentos de población más rápidos mediante instrucciones AVX2". Diario de informática . 61 (1): 111-120. arXiv : 1611.07612 . doi : 10.1093/comjnl/bxx046. S2CID  540973.
  16. ^ Stern & Mahmoud, Diseño de sistemas de comunicaciones , Prentice Hall , 2004, pág. 477 y siguientes.
  17. ^ "Notas de la versión de GCC 3.4". Proyecto GNU .
  18. ^ "Notas de la versión LLVM 1.5". Proyecto LLVM .
  19. ^ "Novedades de Python 3.10". python.org .
  20. ^ "Notas de la versión de GHC 7.4.1".Documentación GHC.
  21. ^ "Capítulo 12.11. Funciones de bits - Manual de referencia de MySQL 5.0".
  22. ^ Metcalf, Michael; Reid, Juan; Cohen, Malcolm (2011). Explicación del Fortran moderno . Prensa de la Universidad de Oxford . pag. 380.ISBN _ 978-0-19-960142-4.
  23. ^ Schwartz, Jake; Grevelle, Rick (20 de octubre de 2003) [1993]. Biblioteca de emuladores HP16C para HP48S/SX. 1,20 (1 ed.) . Consultado el 15 de agosto de 2015 .(NB. Esta biblioteca también funciona en HP 48G / GX / G+ . Más allá del conjunto de funciones del HP-16C, este paquete también admite cálculos para números de coma flotante binarios, octales y hexadecimales en notación científica , además de la notación decimal habitual. Números de punto flotante.)
  24. ^ Bonin, Walter (2019) [2015]. Manual del propietario del WP 43S (PDF) . 0,12 (borrador de edición). pag. 135.ISBN _ 978-1-72950098-9. Consultado el 5 de agosto de 2019 .[2] [3] (314 páginas)
  25. ^ Bonin, Walter (2019) [2015]. Manual de referencia WP 43S (PDF) . 0,12 (borrador de edición). págs. xiii, 104, 115, 120, 188. ISBN 978-1-72950106-1. Consultado el 5 de agosto de 2019 .[4] [5] (271 páginas)
  26. ^ Martín, Ángel M.; McClure, Greg J. (5 de septiembre de 2015). "Módulo emulador HP16C para HP-41CX - Manual del usuario y QRG" (PDF) . Archivado (PDF) desde el original el 27 de abril de 2017 . Consultado el 27 de abril de 2017 .(NB. Más allá del conjunto de funciones HP-16C , esta biblioteca personalizada para HP-41CX amplía la funcionalidad de la calculadora con aproximadamente 50 funciones adicionales).
  27. ^ Martín, Ángel M. (7 de septiembre de 2015). "HP-41: Nuevo emulador HP-16C disponible". Archivado desde el original el 27 de abril de 2017 . Consultado el 27 de abril de 2017 .
  28. ^ Thörngren, Håkan (10 de enero de 2017). "Documentación de Ladybug" (versión 0A ed.) . Consultado el 29 de enero de 2017 .[6]
  29. ^ "Nuevo módulo HP-41 disponible: Ladybug". 2017-01-10. Archivado desde el original el 29 de enero de 2017 . Consultado el 29 de enero de 2017 .
  30. ^ Dale, Paul; Bonin, Walter (2012) [2008]. "Manual del propietario del WP 34S" (PDF) (3.1 ed.) . Consultado el 27 de abril de 2017 .
  31. ^ Bonin, Walter (2015) [2008]. Manual del propietario del WP 34S (3.3 ed.). Plataforma de publicación independiente CreateSpace. ISBN 978-1-5078-9107-0.
  32. ^ "Popcnt de documentación gratuita de Pascal" . Consultado el 7 de diciembre de 2019 .
  33. ^ "JDK-6378821: bitCount() debería usar POPC en procesadores SPARC y AMD+10h". Base de datos de errores de Java . 2006-01-30.
  34. ^ Referencia del conjunto de instrucciones de Blackfin (edición preliminar). Dispositivos analógicos . 2001, págs. 8–24. Número de pieza 82-000410-14.
  35. ^ Lobo, Claire (22 de marzo de 2019). Extensión de manipulación de bits "RISC-V" B "para RISC-V, borrador v0.37" (PDF) . Github .

Otras lecturas

enlaces externos