Una variante de this uno:
double log10_value= log10(value);
double integer_value;
double fractional_value= modf(log10_value, &integer_value);
return fractional_value==0.0;
Tenga en cuenta que la comparación a 0.0
es exacta y no dentro de un épsilon particular, ya que desea asegurarse de que log10_value
es un entero.
EDIT: Dado que esto generó un poco de controversia debido a log10
posiblemente impreciso y la comprensión genérica de que no debe comparar dobles sin épsilon, aquí hay una manera más precisa de determinar si un doble es una potencia de 10 usando solo se duplican las propiedades de potencias de 10 y IEEE 754.
Primero, una aclaración: un doble puede representar hasta 1E22, ya que 1e22 tiene solo 52 bits significativos. Por suerte, 5^22 también Sólo hay 52 bits significativos, por lo que podemos determinar si un doble es (2*5)^n
para n= [0, 22]
:
bool is_pow10(double value)
{
int exponent;
double mantissa= frexp(value, &exponent);
int exponent_adjustment= exponent/10;
int possible_10_exponent= (exponent - exponent_adjustment)/3;
if (possible_10_exponent>=0 &&
possible_10_exponent<=22)
{
mantissa*= pow(2.0, exponent - possible_10_exponent);
return mantissa==pow(5.0, possible_10_exponent);
}
else
{
return false;
}
}
Desde 2^10==1024
, que añade un poco más de importancia que hay que eliminar de la potencia posible de 5.
@Yacoby Una potencia de diez es un número de la forma '10^n' donde' n' es un número entero, por lo que sin duda funcionará. –
Tenga en cuenta que los dobles IEEE754 tienen solo 52 bits de precisión. Como resultado, 10^15 puede representarse exactamente, pero 'doble (10^16) == doble (10^16 + 1)'. Como resultado, tendrá falsos positivos o falsos negativos. Usar 'long long' (donde esté disponible) podría ser mejor. – MSalters
Entonces 10E15 es la potencia máxima de 10 que se puede representar exactamente. En aras de la curiosidad, ¿cuál es el mínimo, 10E-15? –