Sé que Math.sqrt llama a StrictMath.sqrt (double a) Quería ver el código real utilizado para calcularlo.¿Dónde puedo encontrar el código fuente para la función de raíz cuadrada de Java?
Respuesta
Descargue el código fuente del OpenJDK.
No sé exactamente, pero creo que encontrará el algoritmo de Newton en el punto final.
UPD: como los comentarios dicen que la implementación concreta depende de la máquina concreta de Java. Para Windows, es probable que utilice la implementación de ensamblador, donde existe el operador estándar sqrt
Los códigos de ensamblador no dependen del sistema operativo, por lo que no tienen nada que ver con Windows. Pero sí, la JVM favorecerá una instrucción nativa como se detalla en los diversos comentarios de la fuente C. – Joey
Cuando instala un JDK, el código fuente de la biblioteca estándar se puede encontrar en src.zip
. Esto no le ayudará a StrictMath
, aunque, como StrictMath.sqrt(double)
se implementa de la siguiente manera:
public static native double sqrt(double a);
lo que es realmente sólo una llamada nativa y puede ser implementado de manera diferente en diferentes plataformas de Java.
Sin embargo, como la documentación de StrictMath
estados:
para ayudar a asegurar la portabilidad de los programas de Java, las definiciones de algunas de las funciones numéricas en este paquete requieren que producen los mismos resultados que ciertos algoritmos publicados. Estos algoritmos están disponibles en la conocida biblioteca de red
netlib
como el paquete "Librería Matriz libremente distribuible", fdlibm. Estos algoritmos, que están escritos en el lenguaje de programación C, deben entenderse como ejecutados con todas las operaciones de punto flotante siguiendo las reglas de la aritmética de coma flotante de Java.La biblioteca matemática de Java se define con respecto a fdlibm versión 5.3. Donde fdlibm proporciona más de una definición para una función (como acos), use la versión "IEEE 754 core function" (que reside en un archivo cuyo nombre comienza con la letra e). Los métodos que requieren semántica de fdlibm son sin, cos, tan, asin, acos, atan, exp, log, log10, crtrt, atan2, pow, sinh, cosh, tanh, hypot, expm1 y log1p.
Al encontrar la versión adecuada de la fuente fdlibm
, también debe encontrar la implementación exacta utilizada por Java (y según la especificación aquí).
La aplicación es utilizada por fdlibm
static const double one = 1.0, tiny=1.0e-300;
double z;
int sign = (int) 0x80000000;
unsigned r, t1, s1, ix1, q1;
int ix0, s0, q, m, t, i;
ix0 = __HI(x); /* high word of x */
ix1 = __LO(x); /* low word of x */
/* take care of Inf and NaN */
if ((ix0 & 0x7ff00000) == 0x7ff00000) {
return x*x+x; /* sqrt(NaN) = NaN,
sqrt(+inf) = +inf,
sqrt(-inf) = sNaN */
}
/* take care of zero */
if (ix0 <= 0) {
if (((ix0&(~sign)) | ix1) == 0) {
return x; /* sqrt(+-0) = +-0 */
} else if (ix0 < 0) {
return (x-x)/(x-x); /* sqrt(-ve) = sNaN */
}
}
/* normalize x */
m = (ix0 >> 20);
if (m == 0) { /* subnormal x */
while (ix0==0) {
m -= 21;
ix0 |= (ix1 >> 11); ix1 <<= 21;
}
for (i=0; (ix0&0x00100000)==0; i++) {
ix0 <<= 1;
}
m -= i-1;
ix0 |= (ix1 >> (32-i));
ix1 <<= i;
}
m -= 1023; /* unbias exponent */
ix0 = (ix0&0x000fffff)|0x00100000;
if (m&1) { /* odd m, double x to make it even */
ix0 += ix0 + ((ix1&sign) >> 31);
ix1 += ix1;
}
m >>= 1; /* m = [m/2] */
/* generate sqrt(x) bit by bit */
ix0 += ix0 + ((ix1 & sign)>>31);
ix1 += ix1;
q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */
r = 0x00200000; /* r = moving bit from right to left */
while (r != 0) {
t = s0 + r;
if (t <= ix0) {
s0 = t+r;
ix0 -= t;
q += r;
}
ix0 += ix0 + ((ix1&sign)>>31);
ix1 += ix1;
r>>=1;
}
r = sign;
while (r != 0) {
t1 = s1+r;
t = s0;
if ((t<ix0) || ((t == ix0) && (t1 <= ix1))) {
s1 = t1+r;
if (((t1&sign) == sign) && (s1 & sign) == 0) {
s0 += 1;
}
ix0 -= t;
if (ix1 < t1) {
ix0 -= 1;
}
ix1 -= t1;
q1 += r;
}
ix0 += ix0 + ((ix1&sign) >> 31);
ix1 += ix1;
r >>= 1;
}
/* use floating add to find out rounding direction */
if((ix0 | ix1) != 0) {
z = one - tiny; /* trigger inexact flag */
if (z >= one) {
z = one+tiny;
if (q1 == (unsigned) 0xffffffff) {
q1=0;
q += 1;
}
} else if (z > one) {
if (q1 == (unsigned) 0xfffffffe) {
q+=1;
}
q1+=2;
} else
q1 += (q1&1);
}
}
ix0 = (q>>1) + 0x3fe00000;
ix1 = q 1>> 1;
if ((q&1) == 1) ix1 |= sign;
ix0 += (m <<20);
__HI(z) = ix0;
__LO(z) = ix1;
return z;
Mmmm. Es casi demasiado simple :-) –
Simplemente no entiendo cómo se implementa esto sin bucles de longitud variable jajaja. ¿Sabes dónde encontrar una explicación para esto? –
@GershomMaes: Probablemente le preguntaría cómo funciona el algoritmo en uno de los sitios de StackExchange de matemáticas. Los comentarios no son para preguntas. – Joey
Desde que sucede que tiene OpenJDK por ahí, voy a mostrar aquí su implementación.
en el JDK/src/share/nativo/java/lang/StrictMath.c:
JNIEXPORT jdouble JNICALL
Java_java_lang_StrictMath_sqrt(JNIEnv *env, jclass unused, jdouble d)
{
return (jdouble) jsqrt((double)d);
}
jsqrt
se define como sqrt
en el JDK/src/share/nativo/java/lang/fdlibm/src/w_sqrt.c (el nombre se cambió a través del preprocesador):
#ifdef __STDC__
double sqrt(double x) /* wrapper sqrt */
#else
double sqrt(x) /* wrapper sqrt */
double x;
#endif
{
#ifdef _IEEE_LIBM
return __ieee754_sqrt(x);
#else
double z;
z = __ieee754_sqrt(x);
if(_LIB_VERSION == _IEEE_ || isnan(x)) return z;
if(x<0.0) {
return __kernel_standard(x,x,26); /* sqrt(negative) */
} else
return z;
#endif
}
Y __ieee754_sqrt
se define en el JDK/src/share/nativo/java/lang/fdlibm/src/e_sqrt.c como:
#ifdef __STDC__
static const double one = 1.0, tiny=1.0e-300;
#else
static double one = 1.0, tiny=1.0e-300;
#endif
#ifdef __STDC__
double __ieee754_sqrt(double x)
#else
double __ieee754_sqrt(x)
double x;
#endif
{
double z;
int sign = (int)0x80000000;
unsigned r,t1,s1,ix1,q1;
int ix0,s0,q,m,t,i;
ix0 = __HI(x); /* high word of x */
ix1 = __LO(x); /* low word of x */
/* take care of Inf and NaN */
if((ix0&0x7ff00000)==0x7ff00000) {
return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf
sqrt(-inf)=sNaN */
}
/* take care of zero */
if(ix0<=0) {
if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */
else if(ix0<0)
return (x-x)/(x-x); /* sqrt(-ve) = sNaN */
}
/* normalize x */
m = (ix0>>20);
if(m==0) { /* subnormal x */
while(ix0==0) {
m -= 21;
ix0 |= (ix1>>11); ix1 <<= 21;
}
for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1;
m -= i-1;
ix0 |= (ix1>>(32-i));
ix1 <<= i;
}
m -= 1023; /* unbias exponent */
ix0 = (ix0&0x000fffff)|0x00100000;
if(m&1){ /* odd m, double x to make it even */
ix0 += ix0 + ((ix1&sign)>>31);
ix1 += ix1;
}
m >>= 1; /* m = [m/2] */
/* generate sqrt(x) bit by bit */
ix0 += ix0 + ((ix1&sign)>>31);
ix1 += ix1;
q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */
r = 0x00200000; /* r = moving bit from right to left */
while(r!=0) {
t = s0+r;
if(t<=ix0) {
s0 = t+r;
ix0 -= t;
q += r;
}
ix0 += ix0 + ((ix1&sign)>>31);
ix1 += ix1;
r>>=1;
}
r = sign;
while(r!=0) {
t1 = s1+r;
t = s0;
if((t<ix0)||((t==ix0)&&(t1<=ix1))) {
s1 = t1+r;
if(((t1&sign)==sign)&&(s1&sign)==0) s0 += 1;
ix0 -= t;
if (ix1 < t1) ix0 -= 1;
ix1 -= t1;
q1 += r;
}
ix0 += ix0 + ((ix1&sign)>>31);
ix1 += ix1;
r>>=1;
}
/* use floating add to find out rounding direction */
if((ix0|ix1)!=0) {
z = one-tiny; /* trigger inexact flag */
if (z>=one) {
z = one+tiny;
if (q1==(unsigned)0xffffffff) { q1=0; q += 1;}
else if (z>one) {
if (q1==(unsigned)0xfffffffe) q+=1;
q1+=2;
} else
q1 += (q1&1);
}
}
ix0 = (q>>1)+0x3fe00000;
ix1 = q1>>1;
if ((q&1)==1) ix1 |= sign;
ix0 += (m <<20);
__HI(z) = ix0;
__LO(z) = ix1;
return z;
}
hay comentarios copiosas en el archivo que explican los métodos utilizados, que he omitido por razones de brevedad (semi). Here's the file in Mercurial (espero que este sea el camino correcto para enlazar).
más uno para el enlace a la fuente en hg – Will
- 1. ¿Dónde encontrar el código fuente JSSE/JCE de Java 6?
- 2. ¿Dónde encontrar el código fuente de BitTorrent?
- 3. ¿Dónde puedo encontrar el código fuente de Flex?
- 4. ¿Dónde puedo encontrar el código fuente de System.Numerics.BigInteger?
- 5. ¿De dónde puedo encontrar el código fuente del comando cp?
- 6. ¿Dónde puedo encontrar el código fuente de Java para el cifrado Vigenere?
- 7. ¿Metafunción de raíz cuadrada?
- 8. ¿Dónde puedo encontrar la fuente de System.Web.Optimization?
- 9. ¿Dónde puedo encontrar el código fuente JDK 1.5?
- 10. ¿Dónde puedo encontrar un buen código fuente de C++?
- 11. ¿Dónde puedo encontrar el código fuente de las matrices de Java?
- 12. ¿Cómo se implementa la función de raíz cuadrada?
- 13. ¿Dónde puedo encontrar la fuente o el algoritmo de la función hash() de Python?
- 14. Raíz cuadrada para Bigint en F #
- 15. ¿Dónde está el código fuente del compilador de Java?
- 16. Dónde está el código fuente para Html.TextBoxFor
- 17. ¿Dónde puedo encontrar el código fuente para todas las bibliotecas estándar de C?
- 18. ¿Dónde puedo encontrar el código fuente para los comandos básicos de Linux?
- 19. ¿Implementación de hardware de raíz cuadrada?
- 20. ¿Dónde puedo encontrar el código fuente de la llamada del sistema?
- 21. ¿Dónde puedo encontrar la fuente de la jarra springloaded-core?
- 22. ¿Dónde puedo encontrar el código fuente de la clase javax.swing.BorderLayout, por favor?
- 23. ¿Dónde puedo encontrar el código fuente para el complemento Herramientas de desarrollo de Android (ADT) para el IDE de Eclipse?
- 24. raíz cuadrada de seguimiento del valor móvil
- 25. ¿Cómo puedo mejorar este método de raíz cuadrada?
- 26. ¿Dónde puedo encontrar el código fuente para .net CLR y C#?
- 27. ¿Dónde puedo encontrar el código fuente de las utilidades de Unix?
- 28. Java API Código fuente
- 29. ¿Dónde puedo ver el código fuente del Sun JDK?
- 30. Cómo encontrar el código fuente de la función Java nativa llamada
pensé que Intel tenía una instrucción sqrt - esto no es cierto? – Marichyasana