PageRenderTime 25ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/SimpleBrainFuck.Core/Etc/MathHelper.cs

http://ironbrainfuck.codeplex.com
C# | 102 lines | 81 code | 10 blank | 11 comment | 19 complexity | 5e5d5ca3ca2e0cdc19ecd5f911b71b6a MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. namespace ZackFlame.SimpleBrainFuck
  5. {
  6. internal static class MathHelper
  7. {
  8. /// <summary>
  9. /// Разложение числа на множители алгоритмом Ферма.
  10. /// </summary>
  11. /// <param name="n">Разлагаемое число.</param>
  12. /// <returns>Можители числа.</returns>
  13. public static int[] Factorization(int n)
  14. {
  15. short i_max = (short)Math.Floor(Math.Log(n, 2)); // Максимальное кол-во множителей
  16. int[] factors = new Int32[i_max + 1]; // Массив в который будут писацца множители
  17. int next = 1; // Следующий индекс массива
  18. factors[0] = n;
  19. int i = 0;
  20. bool exit = false;
  21. while (!exit)
  22. {
  23. factors[next] = FermatsMethod(ref factors[i]);
  24. if (factors[next] != 0) // Если разложилось, то
  25. next++; // пробуем разложить число на том же индексе
  26. else // Если число простое, то можно брать следующее
  27. if (++i == i_max) // Если весь массив "заполнен", то выходим
  28. exit = true;
  29. }
  30. int newSize = 0;
  31. for (; newSize == 0; i--) // Уменьшаем индекс, как только найдем ненулевой
  32. if (factors[i] != 0) newSize = i + 1; // элемент пербор будет закончен
  33. Array.Resize<int>(ref factors, newSize); // Обрезаем нули
  34. Array.Sort(factors); // Сортируем в порядке возрастания
  35. return factors;
  36. }
  37. /// <summary>
  38. /// Метод Ферма для разложения числа на два простых сомножителя.
  39. /// </summary>
  40. /// <param name="n">Число для разложения и затем сомножитель.</param>
  41. /// <returns>Первый сомножитель.</returns>
  42. private static int FermatsMethod(ref int n)
  43. {
  44. if (n <= 2)
  45. return 0;
  46. if (n % 2 == 0) // Проверка на четность
  47. {
  48. n = n / 2;
  49. return 2;
  50. }
  51. int x = 1 + 2 * Convert.ToInt32(Math.Floor(Math.Sqrt(n)));
  52. int y = 1;
  53. int r = Convert.ToInt32(Math.Pow(Math.Floor(Math.Sqrt(n)), 2)) - n;
  54. int q = n / 2;
  55. bool exit = false;
  56. byte state = 2;
  57. while (!exit)
  58. {
  59. switch (state)
  60. {
  61. case 2:
  62. if (r <= 0)
  63. state = 4;
  64. else
  65. state = 3;
  66. break;
  67. case 3:
  68. r -= y;
  69. y += 2;
  70. if (y > q)
  71. return 0; // Возвращаем ноль, если число простое.
  72. else
  73. state = 2;
  74. break;
  75. case 4:
  76. if (r == 0)
  77. exit = true; // Найдены сомножители!
  78. else
  79. {
  80. r += x;
  81. x += 2;
  82. state = 3;
  83. }
  84. break;
  85. }
  86. }
  87. // Возвращаем первый сомножитель, а через ссылку второй.
  88. n = (x - y) / 2;
  89. return (x + y - 2) / 2;
  90. }
  91. }
  92. }