Ésta es una (extremo) C# versión optimizada del código deleite del Hacker, como se ha mencionado por otros.
Como referencia (en mi pc): Math.Sqrt tarda aproximadamente 35 ns, crtrt < 15 ns.
Se usan multiplicaciones por números pequeños, pero es fácil reemplazarlas por cambios y agrega . Por ejemplo, la mayor multipication (última línea): "12 * z" ==> "(z < < 3) + (z < < 2)"
Es difícil juzgar si el tamaño del código es aceptable para un microcontrolador pequeño
Primer paso: Una búsqueda binaria, las sentencias "if", los valores grandes (> = 1u < < 24) se encuentran relativamente más rápido, valores pequeños (< 64) se manejan durante la búsqueda.
Segundo paso: Un salto en el bucle desenrollado, las "etiquetas".
private static uint cbrt(uint x)
{
uint y = 2, z = 4, b = 0;
if (x < 1u << 24)
if (x < 1u << 12)
if (x < 1u << 06)
if (x < 1u << 03)
return x == 0u ? 0u : 1u;
else
return x < 27u ? 2u : 3u;
else
if (x < 1u << 09) goto L8; else goto L7;
else
if (x < 1u << 18)
if (x < 1u << 15) goto L6; else goto L5;
else
if (x < 1u << 21) goto L4; else goto L3;
else
if (x >= 1u << 30) goto L0;
else
if (x < 1u << 27) goto L2; else goto L1;
L0: x -= 1u << 30; if (x >= 19u << 27)
{ x -= 19u << 27; z = 9; y = 3; } goto M0;
L1: x -= 1u << 27; if (x >= 19u << 24)
{ x -= 19u << 24; z = 9; y = 3; } goto M1;
L2: x -= 1u << 24; if (x >= 19u << 21)
{ x -= 19u << 21; z = 9; y = 3; } goto M2;
L3: x -= 1u << 21; if (x >= 19u << 18)
{ x -= 19u << 18; z = 9; y = 3; } goto M3;
L4: x -= 1u << 18; if (x >= 19u << 15)
{ x -= 19u << 15; z = 9; y = 3; } goto M4;
L5: x -= 1u << 15; if (x >= 19u << 12)
{ x -= 19u << 12; z = 9; y = 3; } goto M5;
L6: x -= 1u << 12; if (x >= 19u << 09)
{ x -= 19u << 09; z = 9; y = 3; } goto M6;
L7: x -= 1u << 09; if (x >= 19u << 06)
{ x -= 19u << 06; z = 9; y = 3; } goto M7;
L8: x -= 1u << 06; if (x >= 19u << 03)
{ x -= 19u << 03; z = 9; y = 3; } goto M8;
M0: y *= 2; z *= 4; b = 3 * y + 3 * z + 1 << 24;
if (x >= b) { x -= b; z += 2 * y + 1; y += 1; }
M1: y *= 2; z *= 4; b = 3 * y + 3 * z + 1 << 21;
if (x >= b) { x -= b; z += 2 * y + 1; y += 1; }
M2: y *= 2; z *= 4; b = 3 * y + 3 * z + 1 << 18;
if (x >= b) { x -= b; z += 2 * y + 1; y += 1; }
M3: y *= 2; z *= 4; b = 3 * y + 3 * z + 1 << 15;
if (x >= b) { x -= b; z += 2 * y + 1; y += 1; }
M4: y *= 2; z *= 4; b = 3 * y + 3 * z + 1 << 12;
if (x >= b) { x -= b; z += 2 * y + 1; y += 1; }
M5: y *= 2; z *= 4; b = 3 * y + 3 * z + 1 << 09;
if (x >= b) { x -= b; z += 2 * y + 1; y += 1; }
M6: y *= 2; z *= 4; b = 3 * y + 3 * z + 1 << 06;
if (x >= b) { x -= b; z += 2 * y + 1; y += 1; }
M7: y *= 2; z *= 4; b = 3 * y + 3 * z + 1 << 03;
if (x >= b) { x -= b; z += 2 * y + 1; y += 1; }
M8: y *= 2; return x <= 3 * y + 12 * z ? y : y + 1;
}
No, que yo sepa, pero se puede generar las terceras potencias de números enteros sucesivos mediante la adición de 7, 19, 37, 61, etc y se puede conseguir esos números mediante la adición de 12, 18, 24, 30, 36, etc. . No es especialmente inteligente o rápido, pero teniendo en cuenta que la raíz cúbica entera de 2^32 sigue siendo solo 1625, no debería tomar tantas iteraciones (todas las cuales consisten en un par de adiciones y una comparación, no mults). editar: así resulta que hay una manera. ¡bueno saber! – harold