Estaba escribiendo un programa en C ++ para encontrar todas las soluciones de una b = c , donde un , b y c juntos utilizan todos los dígitos 0-9 exactamente una vez. El programa enlazadas sobre los valores de una y B , y se pasó una rutina de conteo de dígitos cada vez en una , b y un b para comprobar si la condición dígitos se mostró satisfecho.
Sin embargo, se pueden generar soluciones espurias cuando una b desborda el límite entero. Terminé buscando esto usando un código como:
unsigned long b, c, c_test;
...
c_test=c*b; // Possible overflow
if (c_test/b != c) {/* There has been an overflow*/}
else c=c_test; // No overflow
¿Hay una mejor manera de probar el desbordamiento? Sé que algunos chips tienen un indicador interno que se establece cuando se produce un desbordamiento, pero nunca lo he visto a través de C o C ++.
Tenga en cuenta que el desbordamiento firmado int
es un comportamiento indefinido en C y C ++ y, por lo tanto, debe detectarlo sin causarlo. Para el desbordamiento int firmado antes de la adición, consulte Detección del desbordamiento firmado en C / C ++ .
fuente
-ftrapv
hará que genere un SIGABRT en el desbordamiento de entero (firmado). Ver aquí .clz
instrucción o la__clz(unsigned)
función para determinar el rango del número (donde está su bit más alto). Como no estoy seguro de si esto está disponible en x86 o x64, asumiré que no lo es y diré que encontrar el bit más significativo requerirá las peoreslog(sizeof(int)*8)
instrucciones.Respuestas:
Veo que estás usando enteros sin signo. Por definición, en C (no sé sobre C ++), la aritmética sin signo no se desborda ... por lo tanto, al menos para C, su punto es discutible :)
Con enteros con signo, una vez que se ha desbordado, se ha producido un comportamiento indefinido (UB) y su programa puede hacer cualquier cosa (por ejemplo: hacer que las pruebas no sean concluyentes).
Para crear un programa conforme, debe probar el desbordamiento antes de generar dicho desbordamiento. El método también se puede usar con enteros sin signo:
Para la división (excepto para el
INT_MIN
y-1
caso especial), no hay ninguna posibilidad de pasar por encimaINT_MIN
oINT_MAX
.fuente
x >= 0
-x > 0
será suficiente (six == 0
, entoncesx + a
no puede desbordarse por razones obvias).if ((a < INT_MIN / x))
la prueba es demasiado tarde Seif (x == -1)
necesita una prueba primero.No es una forma de determinar si una operación es probable que rebose, utilizando las posiciones de los uno-bits más significativos de los operandos y un poco de conocimiento básico binario-matemáticas.
Además, cualquiera de los dos operandos dará como resultado (como máximo) un bit más que el bit más alto del operando más grande. Por ejemplo:
Para la multiplicación, cualquiera de los dos operandos dará como resultado (como máximo) la suma de los bits de los operandos. Por ejemplo:
Del mismo modo, puede estimar el tamaño máximo del resultado
a
a la potencia deb
esta manera:(Sustituya el número de bits para su entero objetivo, por supuesto).
No estoy seguro de la forma más rápida de determinar la posición del bit más alto en un número, aquí hay un método de fuerza bruta:
No es perfecto, pero eso le dará una buena idea de si dos números podrían desbordarse antes de realizar la operación. No sé si sería más rápido que simplemente verificar el resultado de la manera que sugirió, debido al bucle en la
highestOneBitPosition
función, pero podría (especialmente si sabía de antemano cuántos bits había en los operandos).fuente
log2
, pero eso no sería necesariamente tan obvio para alguien que no tenía una base matemática.multiplication_is_safe
0x8000 * 0x10000
desbordamiento (las posiciones de bits son 16 + 17 = 33, que es > 32 ), aunque no lo hace porque0x8000 * 0x10000 = 0x80000000
obviamente todavía cabe en un int de 32 bits sin signo. Este es solo uno de los ejemplos de mayo para los que este código no funciona.0x8000 * 0x10001
, ...0x8000 * 0x10000
no es "seguro", según esta definición, aunque resulte estar bien.Clang 3.4+ y GCC 5+ ofrecen funciones aritméticas comprobadas. Ofrecen una solución muy rápida a este problema, especialmente en comparación con las comprobaciones de seguridad de prueba de bits.
Para el ejemplo en la pregunta de OP, funcionaría así:
La documentación de Clang no especifica si
c_test
contiene el resultado desbordado si ocurrió un desbordamiento, pero la documentación de GCC dice que sí. Dado que a estos dos les gusta ser__builtin
compatibles, probablemente sea seguro asumir que así es como funciona Clang.Hay una
__builtin
para cada operación aritmética que puede desbordarse (suma, resta, multiplicación), con variantes con signo y sin signo, para tamaños int, tamaños largos y tamaños largos largos. La sintaxis para el nombre es__builtin_[us](operation)(l?l?)_overflow
:u
para no firmado os
para firmado ;add
,sub
omul
;l
sufijo significa que los operandos sonint
s; unol
mediolong
; dosl
s significanlong long
.Entonces, para una suma de enteros largos marcados y marcados, sería
__builtin_saddl_overflow
. La lista completa se puede encontrar en la página de documentación de Clang .GCC 5+ y Clang 3,8+ ofrecen, además, órdenes internas genéricos que funcionan sin especificar el tipo de los valores:
__builtin_add_overflow
,__builtin_sub_overflow
y__builtin_mul_overflow
. Estos también funcionan en tipos más pequeños queint
.Los componentes se reducen a lo que es mejor para la plataforma. En x86, verifican el acarreo, desbordamiento y firman banderas.
El cl.exe de Visual Studio no tiene equivalentes directos. Para sumas y restas sin firmar, incluso
<intrin.h>
le permitirá usaraddcarry_uNN
ysubborrow_uNN
(donde NN es el número de bits, comoaddcarry_u8
osubborrow_u64
). Su firma es un poco obtusa:c_in
/b_in
es el indicador de acarreo / préstamo en la entrada y el valor de retorno es el transporte / préstamo en la salida No parece tener equivalentes para operaciones con signo o multiplicaciones.De lo contrario, Clang para Windows ahora está listo para la producción (lo suficientemente bueno para Chrome), por lo que también podría ser una opción.
fuente
__builtin_sub_overflow
definitivamente no está en Clang 3.4.__builtin_add_overflow
y los amigos ya deberían estar disponibles en Clang 3.8.Algunos compiladores proporcionan acceso al indicador de desbordamiento de enteros en la CPU que luego puede probar, pero esto no es estándar.
También puede probar la posibilidad de desbordamiento antes de realizar la multiplicación:
fuente
b == ULONG_MAX / a
? Entonces todavía puede encajar, dado que sea
divideULONG_MAX
sin residuos.Advertencia: GCC puede optimizar una comprobación de desbordamiento al compilar con
-O2
. La opción-Wall
le dará una advertencia en algunos casos comopero no en este ejemplo:
La única forma segura es verificar el desbordamiento antes de que ocurra, como se describe en el documento del CERT , y esto sería increíblemente tedioso de usar sistemáticamente.
Compilar con
-fwrapv
resuelve el problema, pero deshabilita algunas optimizaciones.Necesitamos desesperadamente una mejor solución. Creo que el compilador debería emitir una advertencia por defecto al hacer una optimización que se basa en que no se produzca un desbordamiento. La situación actual le permite al compilador optimizar una verificación de desbordamiento, lo cual es inaceptable en mi opinión.
fuente
for(int k = 0; k < 5; k++) {...}
debería hacer una advertencia?k
se pueden determinar fácilmente en tiempo de compilación. El compilador no tiene que hacer ninguna suposición.n
es inferior a 32, antes de emitir una instrucción de cambio que solo utiliza los 5 bits inferiores den
?Clang ahora admite comprobaciones dinámicas de desbordamiento para enteros con y sin signo. Consulte el modificador -fsanitize = integer . Por ahora, es el único compilador de C ++ con comprobación de desbordamiento dinámico totalmente compatible con fines de depuración.
fuente
Veo que muchas personas respondieron la pregunta sobre el desbordamiento, pero quería abordar su problema original. Dijo que el problema era encontrar a b = c de modo que todos los dígitos se usen sin repetir. Ok, eso no es lo que preguntó en esta publicación, pero sigo pensando que era necesario estudiar el límite superior del problema y concluir que nunca necesitaría calcular o detectar un desbordamiento (nota: no soy competente) en matemáticas, así que hice esto paso a paso, pero el resultado final fue tan simple que podría tener una fórmula simple).
El punto principal es que el límite superior que requiere el problema para a, b o c es 98.765.432. De todos modos, comenzando dividiendo el problema en las partes triviales y no triviales:
Ahora solo tenemos que mostrar que no hay otra solución posible y que solo las permutaciones son válidas (y luego el código para imprimirlas es trivial). Volvemos al límite superior. En realidad, el límite superior es c ≤ 98.765.432. Es el límite superior porque es el número más grande con 8 dígitos (10 dígitos en total menos 1 para cada ayb). Este límite superior es solo para c porque los límites para ayb deben ser mucho más bajos debido al crecimiento exponencial, como podemos calcular, variando b de 2 al límite superior:
Observe, por ejemplo, la última línea: dice que 1.97 ^ 27 ~ 98M. Entonces, por ejemplo, 1 ^ 27 == 1 y 2 ^ 27 == 134.217.728 y eso no es una solución porque tiene 9 dígitos (2> 1.97, por lo que en realidad es más grande de lo que debería probarse). Como se puede ver, las combinaciones disponibles para probar ayb son realmente pequeñas. Para b == 14, necesitamos probar 2 y 3. Para b == 3, comenzamos en 2 y terminamos en 462. Todos los resultados se otorgan a menos de ~ 98M.
Ahora solo pruebe todas las combinaciones anteriores y busque las que no repitan ningún dígito:
Ninguno de ellos coincide con el problema (que también se puede ver por la ausencia de '0', '1', ..., '9').
El código de ejemplo que lo resuelve sigue. También tenga en cuenta que está escrito en Python, no porque necesite enteros de precisión arbitrarios (el código no calcula nada más grande que 98 millones), sino porque descubrimos que la cantidad de pruebas es tan pequeña que deberíamos usar un lenguaje de alto nivel para haga uso de sus contenedores y bibliotecas incorporados (también tenga en cuenta: el código tiene 28 líneas).
fuente
Aquí hay una solución "no portátil" a la pregunta. Las CPU Intel x86 y x64 tienen el denominado registro EFLAGS , que el procesador completa después de cada operación aritmética de enteros. Omitiré una descripción detallada aquí. Las banderas relevantes son la Bandera de "Desbordamiento" (máscara 0x800) y la Bandera de "Llevar" (máscara 0x1). Para interpretarlos correctamente, uno debe considerar si los operandos son de tipo con signo o sin signo.
Aquí hay una forma práctica de verificar las banderas desde C / C ++. El siguiente código funcionará en Visual Studio 2005 o posterior (tanto de 32 como de 64 bits), así como en GNU C / C ++ de 64 bits.
Si los operandos se multiplicaron sin desbordamiento, obtendría un valor de retorno de 0
query_intel_eflags(0x801)
, es decir, no se establecen ni los indicadores de acarreo ni de desbordamiento. En el código de ejemplo proporcionado de main (), se produce un desbordamiento y los dos indicadores se establecen en 1. Esta comprobación no implica ningún cálculo adicional, por lo que debería ser bastante rápido.fuente
Si tiene un tipo de datos que es más grande que el que desea probar (digamos que agrega 32 bits y tiene un tipo de 64 bits), esto detectará si ocurrió un desbordamiento. Mi ejemplo es para un complemento de 8 bits. Pero se puede ampliar.
Se basa en los conceptos explicados en esta página: http://www.cs.umd.edu/class/spring2003/cmsc311/Notes/Comb/overflow.html
Para un ejemplo de 32 bits, se
0xFF
convierte0xFFFFFFFF
y se0x80
convierte0x80000000
y finalmente seuint16_t
convierte en auint64_t
.NOTA : esto detecta desbordamientos de suma / resta enteros, y me di cuenta de que su pregunta implica la multiplicación. En cuyo caso, la división es probablemente el mejor enfoque. Esta es comúnmente una forma en que las
calloc
implementaciones se aseguran de que los parámetros no se desborden, ya que se multiplican para obtener el tamaño final.fuente
La forma más simple es convertir su
unsigned long
s enunsigned long long
s, hacer su multiplicación y comparar el resultado con 0x100000000LL.Probablemente encontrará que esto es más eficiente que hacer la división como lo hizo en su ejemplo.
Ah, y funcionará tanto en C como en C ++ (ya que ha etiquetado la pregunta con ambos).
Acabo de leer el manual de glibc . Hay una mención de una trampa de desbordamiento de enteros (
FPE_INTOVF_TRAP
) como parte deSIGFPE
. Eso sería ideal, aparte de las partes desagradables en el manual:Un poco de vergüenza realmente.
fuente
ULONG_MAX
cuál es más fácil de escribir y más portátil que la codificación rígida0x100000000
.long
ylong long
son del mismo tamaño (por ejemplo, en muchos compiladores de 64 bits).Aquí hay una manera realmente rápida de detectar el desbordamiento de al menos las adiciones, lo que podría dar lugar a la multiplicación, división y potencia de.
La idea es que exactamente porque el procesador simplemente permitirá que el valor vuelva a cero y que C / C ++ se abstraiga de cualquier procesador específico, puede:
Esto garantiza que si un operando es cero y el otro no, entonces el desbordamiento no se detectará falsamente y es significativamente más rápido que muchas operaciones NOT / XOR / AND / test como se sugirió anteriormente.
Como se señaló, este enfoque, aunque es mejor que otras formas más elaboradas, sigue siendo optimizable. La siguiente es una revisión del código original que contiene la optimización:
Una forma más eficiente y económica de detectar el desbordamiento de multiplicación es:
Esto da como resultado UINT32_MAX en desbordamiento o el resultado de la multiplicación. Es un comportamiento estrictamente indefinido permitir que la multiplicación proceda para enteros con signo en este caso.
fuente
x+y>=256
yvalue=x+y-256
. Comoy<256
siempre es cierto, (y-256) es negativo yvalue < x
siempre es cierto. La prueba para el caso no desbordante es bastante similar.uint32_t x[N], y[N], z[N], carry=0; for (int i = 0; i < N; i++) { z[i] = x[i] + y[i] + carry; carry = z[i] < (x[i] | y[i]); }
Si no conoceor
los valores, no podrá distinguir entre un operando y el bit de acarreo es cero y un operando es0xffffffff
y el bit de acarreo es uno.No puede acceder al indicador de desbordamiento desde C / C ++.
Algunos compiladores le permiten insertar instrucciones de captura en el código. En GCC la opción es
-ftrapv
.Lo único que puede hacer independientemente del compilador portátil y es verificar los desbordamientos por su cuenta. Tal como lo hiciste en tu ejemplo.
Sin embargo,
-ftrapv
parece no hacer nada en x86 usando el último GCC. Supongo que es un remanente de una versión anterior o específica de alguna otra arquitectura. Esperaba que el compilador insertara un código de operación INTO después de cada adición. Lamentablemente no hace esto.fuente
Para enteros sin signo, solo verifique que el resultado sea más pequeño que uno de los argumentos:
Para enteros con signo, puede verificar los signos de los argumentos y del resultado.
Los enteros de diferentes signos no pueden desbordarse, y los enteros del mismo signo se desbordan solo si el resultado es de un signo diferente:
fuente
char result = (char)127 + (char)3;
sería -126; más pequeño que ambos operandos.Necesitaba responder esta misma pregunta para los números de coma flotante, donde el enmascaramiento y el desplazamiento de bits no parecen prometedores. El enfoque en el que me decidí funciona para números con signo y sin signo, enteros y de coma flotante. Funciona incluso si no hay un tipo de datos más grande para promover los cálculos intermedios. No es el más eficiente para todos estos tipos, pero como funciona para todos ellos, vale la pena usarlo.
Prueba de desbordamiento firmada, suma y resta:
Obtenga las constantes que representan los valores más grandes y más pequeños posibles para el tipo, MAXVALUE y MINVALUE.
Calcule y compare los signos de los operandos.
a. Si cualquiera de los valores es cero, entonces ni la suma ni la resta pueden desbordarse. Omita las pruebas restantes.
si. Si los signos son opuestos, entonces la suma no puede desbordarse. Omita las pruebas restantes.
C. Si los signos son iguales, entonces la resta no puede desbordarse. Omita las pruebas restantes.
Prueba de desbordamiento positivo de MAXVALUE.
a. Si ambos signos son positivos y MAXVALUE - A <B, entonces la adición se desbordará.
si. Si el signo de B es negativo y MAXVALUE - A <-B, entonces la resta se desbordará.
Prueba de desbordamiento negativo de MINVALUE.
a. Si ambos signos son negativos y MINVALUE - A> B, la adición se desbordará.
si. Si el signo de A es negativo y MINVALUE - A> B, entonces la resta se desbordará.
De lo contrario, no hay desbordamiento.
Prueba de desbordamiento firmada, multiplicación y división:
Obtenga las constantes que representan los valores más grandes y más pequeños posibles para el tipo, MAXVALUE y MINVALUE.
Calcule y compare las magnitudes (valores absolutos) de los operandos con uno. (A continuación, suponga que A y B son estas magnitudes, no los originales firmados).
a. Si cualquiera de los valores es cero, la multiplicación no puede desbordarse y la división producirá cero o un infinito.
si. Si cualquiera de los valores es uno, la multiplicación y la división no pueden desbordarse.
C. Si la magnitud de un operando está por debajo de uno y el otro es mayor que uno, la multiplicación no puede desbordarse.
re. Si las magnitudes son menos de uno, la división no puede desbordarse.
Prueba de desbordamiento positivo de MAXVALUE.
a. Si ambos operandos son mayores que uno y MAXVALUE / A <B, entonces la multiplicación se desbordará.
si. Si B es menor que uno y MAXVALUE * B <A, entonces la división se desbordará.
De lo contrario, no hay desbordamiento.
Nota: El desbordamiento mínimo de MINVALUE es manejado por 3, porque tomamos valores absolutos. Sin embargo, si ABS (MINVALUE)> MAXVALUE, tendremos algunos falsos positivos raros.
Las pruebas de subflujo son similares, pero involucran EPSILON (el número positivo más pequeño mayor que cero).
fuente
1.0e-200 / 1.0e200
sería un ejemplo de un flujo inferior real, suponiendo que IEEE se duplica. El término correcto aquí, en cambio, es desbordamiento negativo. </pedantic>1/INT_MAX
podría considerarse un subflujo, pero el lenguaje simplemente ordena el truncamiento a cero.El CERT ha desarrollado un nuevo enfoque para detectar e informar el desbordamiento de enteros firmados, el ajuste de enteros sin firmar y el truncamiento de enteros utilizando el modelo de enteros de rango infinito "AIR". El CERT ha publicado un informe técnico que describe el modelo y produjo un prototipo funcional basado en GCC 4.4.0 y GCC 4.5.0.
El modelo entero AIR produce un valor equivalente a uno que se habría obtenido usando enteros de rango infinito o da como resultado una violación de restricción de tiempo de ejecución. A diferencia de los modelos enteros anteriores, los enteros AIR no requieren trampas precisas y, en consecuencia, no rompen ni inhiben la mayoría de las optimizaciones existentes.
fuente
Otra herramienta interesante es IOC: un comprobador de desbordamiento de enteros para C / C ++ .
Este es un compilador de Clang parcheado , que agrega controles al código en tiempo de compilación.
Obtiene una salida como esta:
fuente
Otra variante de una solución, usando lenguaje ensamblador, es un procedimiento externo. Este ejemplo para la multiplicación de enteros sin signo usando g ++ y fasm en Linux x64.
Este procedimiento multiplica dos argumentos enteros sin signo (32 bits) (de acuerdo con la especificación para amd64 (sección 3.2.3 Paso de parámetros ).
(edi y esi se registran en mi código)) y devuelve el resultado o 0 si se ha producido un desbordamiento.
Prueba:
Enlace el programa con el archivo de objeto asm. En mi caso, en Qt Creator , agréguelo a
LIBS
un archivo .pro.fuente
Calcule los resultados con dobles. Tienen 15 dígitos significativos. Su requisito tiene un límite superior duro en c de 10 8 : puede tener como máximo 8 dígitos. Por lo tanto, el resultado será preciso si está dentro del rango, y de lo contrario no se desbordará.
fuente
Pruebe esta macro para probar el bit de desbordamiento de las máquinas de 32 bits (adaptó la solución de Angel Sinigersky)
Lo definí como una macro porque de lo contrario el bit de desbordamiento se habría sobrescrito.
Posterior es una pequeña aplicación con el segmento de código anterior:
fuente
_MSC_VER
aunque las compilaciones de MS rechazarán el código).Catching Integer Overflows en C señala una solución más general que la discutida por CERT (es más general en términos de tipos manejados), incluso si requiere algunas extensiones de GCC (no sé cuán ampliamente son compatibles).
fuente
No estoy de acuerdo con esto Puede escribir un lenguaje ensamblador en línea y usar una
jo
instrucción (salto de desbordamiento) suponiendo que está en x86 para atrapar el desbordamiento. Por supuesto, su código ya no sería portátil para otras arquitecturas.Mira
info as
yinfo gcc
.fuente
Para ampliar la respuesta de Head Geek, hay una forma más rápida de hacer el
addition_is_safe
;Esto utiliza una arquitectura de máquina segura, ya que los enteros sin signo de 64 bits y 32 bits seguirán funcionando bien. Básicamente, creo una máscara que enmascarará todo menos el bit más significativo. Luego, enmascaro ambos enteros, y si alguno de ellos no tiene ese bit establecido, entonces la suma es segura.
Esto sería aún más rápido si preinicializa la máscara en algún constructor, ya que nunca cambia.
fuente
UINT_MAX + 1
. Después del enmascaramiento,a
se establecerá el bit alto, pero1
se convertirá en cero y, por lo tanto, la función volverátrue
, la adición es segura, pero se dirige directamente al desbordamiento.mozilla::CheckedInt<T>
proporciona matemática de enteros con desbordamiento para el tipo de enteroT
(utilizando intrínsecos del compilador en clang y gcc según esté disponible). El código es bajo MPL 2.0 y depende de tres (IntegerTypeTraits.h
,Attributes.h
yCompiler.h
) otros sólo de encabezado no estándar cabeceras Library Plus Mozilla específica maquinaria afirmación . Probablemente desee reemplazar la maquinaria de aserción si importa el código.fuente
La respuesta de MSalter es una buena idea.
Si se requiere el cálculo de enteros (para precisión), pero el punto flotante está disponible, puede hacer algo como:
fuente
(c * log(a) < max_log)
, dondeconst double max_log = log(UINT_MAX)
El conjunto de instrucciones x86 incluye una instrucción de multiplicación sin signo que almacena el resultado en dos registros. Para usar esa instrucción de C, se puede escribir el siguiente código en un programa de 64 bits (GCC):
Para un programa de 32 bits, uno necesita hacer que el resultado sea de 64 bits y los parámetros de 32 bits.
Una alternativa es utilizar el intrínseco dependiente del compilador para verificar el registro del indicador. La documentación de GCC para el desbordamiento intrínseco se puede encontrar en 6.56 Funciones incorporadas para realizar operaciones aritméticas con verificación de desbordamiento .
fuente
__uint128
para evitar el desbordamiento firmado y el desplazamiento a la derecha de un valor negativo.fuente
Una forma limpia de hacerlo sería anular todos los operadores (+ y * en particular) y verificar un desbordamiento antes de realizar las operaciones.
fuente
Depende de para qué lo uses. Al realizar sumas o multiplicaciones largas sin signo (DWORD), la mejor solución es usar ULARGE_INTEGER.
ULARGE_INTEGER es una estructura de dos DWORD. Se puede acceder al valor completo como "QuadPart", mientras que la DWORD alta se accede como "HighPart" y la DWORD baja se accede como "LowPart".
Por ejemplo:
fuente
ULARGE_INTEGER
.Para realizar una multiplicación sin signo sin desbordarse de forma portátil, se puede utilizar lo siguiente:
fuente
La forma sencilla de probar el desbordamiento es validar comprobando si el valor actual es menor que el valor anterior. Por ejemplo, suponga que tiene un bucle para imprimir las potencias de 2:
Agregar desbordamiento comprobando la forma en que describí los resultados en esto:
Funciona tanto para valores sin signo como para valores con signo positivo y negativo.
Por supuesto, si quisiera hacer algo similar para disminuir los valores en lugar de aumentar los valores, voltearía el
<=
signo para hacerlo>=
, suponiendo que el comportamiento del desbordamiento sea el mismo que el del desbordamiento. Honestamente, eso es lo más portátil posible sin acceso al indicador de desbordamiento de una CPU (y eso requeriría un código de ensamblaje en línea, lo que hace que su código no sea portátil en todas las implementaciones de todos modos).fuente