/// <summary> /// Returns the integer part of the square root /// of the number. /// </summary> /// <remarks>This method works only for integer numeric types.</remarks> /// <param name="number">A strictly positive number for which the integer part of its square root is to be found.</param> /// <returns>The integer part of the square root of the <paramref name="number"/>.</returns> public static LongInt <B> SquareRootInteger(LongInt <B> number) { Contract.Requires <ArgumentNullException>(number != null, "number"); Contract.Requires <ArgumentOutOfRangeException>(number > 0); LongInt <B> firstEstimate = number; // Имеет смысл находить лучшее, чем само число, // первое приближение, только в том случае, // если число имеет длину более 1. if (number.Length > 1) { // Для курсача - доказать, что это хуже, чем то, что незакомментировано // // firstEstimate = LongInt<B>.CreatePowerOfBase((number.Length + 1) / 2); if (!BASE_IS_FULL_SQUARE || number.Length % 2 == 0) { firstEstimate = LongInt <B> .CreatePowerOfBase((number.Length + 1) / 2); } else { firstEstimate = LongInt <B> .CreatePowerOfBase(number.Length / 2); firstEstimate[firstEstimate.Length - 1] = LongInt <B> .Helper.BASE_SQRT_FLOOR; } } return (WhiteMath <LongInt <B>, CalcLongInt <B> > .SquareRootInteger(number, firstEstimate)); }
/// <summary> /// Returns the next non-negative <c>LongInt<<typeparamref name="B"/>></c> /// number which is less than <paramref name="maxExclusive"/>. /// </summary> /// <param name="maxExclusive">The upper exclusive bound of generated numbers.</param> /// <returns> /// A non-negative <c>LongInt<<typeparamref name="B"/>></c> number which /// is less than <paramref name="maxExclusive"/>. /// </returns> public LongInt <B> Next(LongInt <B> maxExclusive) { Contract.Requires <ArgumentNullException>(maxExclusive != null, "maxExclusive"); Contract.Requires <ArgumentOutOfRangeException>(maxExclusive > 0, "The maximum exclusive bound should be a positive number."); LongInt <B> basePowered = LongInt <B> .CreatePowerOfBase(maxExclusive.Length); LongInt <B> upperBound; if (this.lastMaxExclusive != maxExclusive) { // Мы будем генерировать ВСЕ цифры от 0 до BASE - 1. // НО: // Мы отбрасываем верхнюю границу, где приведение по модулю maxExclusive // даст нам лишнюю неравномерность. // Мы можем использовать только интервал, содержащий целое число чисел maxExclusive. // Тогда спокойно приводим по модулю и наслаждаемся равномерностью. // Например, если мы генерируем цифирки по основанию 10, и хотим число от [0; 12), // то нам нужно отбрасывать начиная с floor(10^2 / 12) * 12 = 96. upperBound = Max_BinarySearch((LongInt <B>) 1, LongInt <B> .BASE, (res => LongInt <B> .Helper.MultiplyFFTComplex(res, maxExclusive) <= basePowered)) * maxExclusive; // upperBound = multiplication(basePowered / maxExclusive, maxExclusive); this.lastMaxExclusive = maxExclusive; this.lastBound = upperBound; } else { upperBound = this.lastBound; } LongInt <B> result = new LongInt <B>(); REPEAT: result.Digits.Clear(); for (int i = 0; i < maxExclusive.Length; i++) { result.Digits.Add(intGenerator.Next(0, LongInt <B> .BASE)); } result.DealWithZeroes(); if (result >= upperBound) { ++TotalRejected; goto REPEAT; } // Возвращаем остаток от деления. // return result % maxExclusive; LongInt <B> divisionResult = Max_BinarySearch((LongInt <B>) 0, LongInt <B> .BASE, (res => LongInt <B> .Helper.MultiplyFFTComplex(res, maxExclusive) <= result)); return(result - LongInt <B> .Helper.MultiplyFFTComplex(divisionResult, maxExclusive)); }
/// <summary> /// Returns the next non-negative <c>LongInt<<typeparamref name="B"/>></c> /// number which is less than <paramref name="maxExclusive"/>. /// </summary> /// <param name="maxExclusive">The upper exclusive bound of generated numbers.</param> /// <returns> /// A non-negative <c>LongInt<<typeparamref name="B"/>></c> number which /// is less than <paramref name="maxExclusive"/>. /// </returns> public LongInt <B> Next(LongInt <B> maxExclusive) { Contract.Requires <ArgumentNullException>(maxExclusive != null, "maxExclusive"); Contract.Requires <ArgumentOutOfRangeException>(maxExclusive > 0, "The maximum exclusive bound should be a positive number."); // Мы будем генерировать ВСЕ цифры от 0 до BASE - 1. // НО: // Мы отбрасываем верхнюю границу, где приведение по модулю maxExclusive // даст нам лишнюю неравномерность. // Мы можем использовать только интервал, содержащий целое число чисел maxExclusive. // Тогда спокойно приводим по модулю и наслаждаемся равномерностью. // Например, если мы генерируем цифирки по основанию 10, и хотим число от [0; 12), // то нам нужно отбрасывать начиная с floor(10^2 / 12) * 12 = 96. LongInt <B> upperBound = (LongInt <B> .CreatePowerOfBase(maxExclusive.Length) / maxExclusive) * maxExclusive; LongInt <B> result = new LongInt <B>(); REPEAT: result.Digits.Clear(); for (int i = 0; i < maxExclusive.Length; i++) { result.Digits.Add(intGenerator.Next(0, LongInt <B> .BASE)); } result.DealWithZeroes(); if (result >= upperBound) { ++TotalRejected; goto REPEAT; } return(result % maxExclusive); }