/Sqrt(x).java

https://github.com/cherryljr/LintCode · Java · 94 lines · 42 code · 9 blank · 43 comment · 8 complexity · b028dba7b6281b3141a9a1cba96e4282 MD5 · raw file

  1. /*
  2. Description
  3. Implement int sqrt(int x).
  4. Compute and return the square root of x.
  5. Example
  6. sqrt(3) = 1
  7. sqrt(4) = 2
  8. sqrt(5) = 2
  9. sqrt(10) = 3
  10. Challenge
  11. O(log(x))
  12. */
  13. /**
  14. * 因为精确度只要求到 整形, 故本题是个很简单的 二分查找法的题目.
  15. * 基本上按照 Binary Search Template 编写即可。在这里就不扯太多了。
  16. *
  17. * 但是之所以编写该题有两个原因。
  18. * 1. 如果对精确度有进一步要求呢?
  19. * 这个时候需要用到的高效算法便是 牛顿迭代法。 算法第四版 P13 有笔记
  20. * 不清楚的朋友们可以移步:https://www.zhihu.com/question/20690553
  21. * 这里对它的数学原理进行了很好的分析
  22. * 2. 瞻仰一下卡神的 Magic Number
  23. * 该段源码被应用于 《雷神之锤3》
  24. * Click here for detials: https://en.wikipedia.org/wiki/Fast_inverse_square_root
  25. */
  26. // Binary Search (upper bound)
  27. public class Solution {
  28. /**
  29. * @param x: An integer
  30. * @return: The sqrt of x
  31. */
  32. public int sqrt(int x) {
  33. if (x == 0) {
  34. return 0;
  35. }
  36. // find the last number which square of it <= x
  37. // 注意数据类型要设置成 long 才行,不然会导致计算结果出错
  38. long start = 1, end = x;
  39. while (start < end) {
  40. long mid = start + ((end - start + 1) >> 1);
  41. if (x >= mid * mid) {
  42. start = mid;
  43. } else {
  44. end = mid - 1;
  45. }
  46. }
  47. return (int)end;
  48. }
  49. }
  50. // Newton-Raphson method
  51. class Solution {
  52. /**
  53. * @param x a double
  54. * @return the square root of x
  55. */
  56. public int sqrt(int x) {
  57. // 更周全的做法是对 负数进行 判断
  58. if (x == 0) {
  59. return 0;
  60. }
  61. double err = 1e-12; // 精度设置
  62. double t = x;
  63. while (Math.abs(t - x/t) > err * t) {
  64. t = (x / t + t) / 2.0;
  65. }
  66. return (int)t;
  67. }
  68. }
  69. // Magic Number 0x5f3759df !!! So Amazing
  70. // 雷神之锤3 源码
  71. float Q_rsqrt(float number) {
  72. long i;
  73. float x2, y;
  74. const float threehalfs = 1.5F;
  75. x2 = number * 0.5F;
  76. y = number;
  77. i = * ( long * ) &y; // evil floating point bit level hacking
  78. i = 0x5f3759df - ( i >> 1 ); // what the fuck?
  79. y = * ( float * ) &i;
  80. y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration
  81. // y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed
  82. return y;
  83. }