Можно ли обойтись без длинной арифметики ?
Есть два масива А и Б, в каждом по 100 000 елементов (цифри от 1 до 10).
Для каждого масива нужно перемножыть все его елементы и сказать какое произведение больше или они ровны.
Я делал через длинную арифметику но мое решение не подходило по времени выполения, товарищи делали примерно так
for (int i = 0; i < 100 000; i++){
stepA += ln(A);
}
а потом сравнивали stepA, stepB.
Вот мне интересно можно ли придумать такие входние данние, где точности при таком решении не хватит.
Математики, просветите пожалуйста.
Для каждого из этих чисел получить данные 1^a1 * 2^a2 * ... * a9.
Потом "сократить" эти массивы, и дальше как нибудь анализировать полученные данные.
Для каждого из этих чисел получить данные 1^a1 * 2^a2 * ... * a9.
Потом "сократить" эти массивы, и дальше как нибудь анализировать полученные данные.
По поводу сокращения - не поможет. Если в одном масиве сплошные 7, а в другом 5 - не сократится. Конечно можно понять что 7 > 5. Ну а если в первом только 7 и 3, а в другом 5 - и не сократится и фиг его знает где меньше.
Меня больше интересует вариант с логарифмами. Слону понятно что exp(stepA) нам не даст точного произведения, но можно ли подобрать два таких масива для которых произведения будут немного отличатся, а для значения их логарифмов (то что я не совсем удачно назвал stepA) не хватит точности, чтоб ето проверить. Или же разница для двох самых близких произведений из 100 000 елементов будет настолько большая, что решение с логарифмами всегда даст правильный ответ ?
Я поспешил с самокритикой (коорую уже удалил).
Не скоротится. 100 перемножених 7-ок не скоротятся с 100 премножеными 5-ками.
for (int i = 0; i < 100 000; i++){
stepA += ln(A);
}
А может сделать по-другому?
for (int i = 0; i < 100 000; i++){
result *= A/B;
}
Ну а потом сравниваем result с 1.
for (int i = 0; i < 100 000; i++){
result *= A/B;
}
Ну а потом сравниваем result с 1.
(1/10)^{всяко меньше 50 000} будет нулю равняться, так что ничего хорошенго не получится тоже. Сначала нужно какую-нибудь сортировку хитрую применять, что тоже времени дохера сожрет.
Тогда делаем то же самое только result будет массивом. Когда текущее значение элемента массива приближается к максимальному или минимальному значению начинаем писать в следующий элемент массива. После пробега по всем данным анализируем данные в массиве результатов: перемножаем максимумы и минимумы и т. д.
Как вариант с составлениями массивов типа число--сколько раз повторяется. Если возводить эти числа в степени (=число повторений) сопроцессором (задать принудительно тип long double), получится быстрее.
Для 1 массива заведем 2 переменные ( man - длинное вещественное, por - длинное целое ).
Далее пример:
M1 = 22*33 *44*55
man = 0.100000 por = 1 (умножаем на 22 и нормализуем)
man = 0.220000 por = 2 (умножаем на 33 и нормализуем)
man = 0.726000 por = 3 (умножаем на 44 и нормализуем)
man = 0.319440 por = 5 (умножаем на 55 и нормализуем)
man = 0.175692 por = 7 (запоминаем ответ)
M2 = 66*77*88
man = 0.100000 por = 1 (умножаем на 66 и нормализуем)
man = 0.660000 por = 2 (умножаем на 77 и нормализуем)
man = 0.508200 por = 4 (умножаем на 88 и нормализуем)
man = 0.447216 por = 6 (запоминаем ответ)
В этом примере первое произведение больше даже по порядку (por = 7).
Равентство нужно проверять отдельно (как правильно сказали выше, все элементы должны сократиться).
Спасибо всем за интересные решения.
Но вопрос хватит ли точности остается открытым.
Можно ли подобрать такие масивы при которых не хватит точности для логарифмов или для решения от Alex_soldier ? Мой знакомый утверждает что решение с логарифмами точно не даст ошибки при любом входе, но почему ето так он не обяснил. Ну он математик, ему виднее, но сам я не могу понять почему нельзя подобрать два произведения которые будут отличатся совсем немного друг от друга.
Смотри. Чему ровно ln(10^100000). Я не знаю. А в том варианте который я в начале привел с логарифмами мои знакомые сравнивают именно такие результаты.
В твоем случае интересует man. Хватит ли у него етих старшых розрядов чтоб отличить два произведения которые близки между собой даже припуская, что при умножении не будет погрешности.
Если отбросить погрешности логарифмирования, то получается примерно тоже самое - ошибка младшего разряда.
Я не случайно написал про отдельную проверку равенства.
А вот самый худший из вариантов - когда произведения ПРАКТИЧЕСКИ совпадают.
Тут уж совсем плохо.
Кстати, как вариант - при перемножении хранить и сколько-то младших разрядов. Тогда будет теряться только середина.
В общем же случае для полноценного сравнения нужны все цифры чисел.
Я пошел учить математику :(.
За обяснения по точности спасибо. Больше у меня вопросов нет.