У меня есть массив чисел, которые могут иметь до 8 десятичных знаков, и мне нужно найти наименьшее общее число, на которое я могу умножить их, чтобы они были целыми числами. Мне это нужно, чтобы все исходные числа можно было умножить до одного и того же масштаба и обработать в запечатанной системе, которая будет работать только с целыми числами, затем я могу получить результаты и разделить их на общий множитель, чтобы получить мои относительные результаты. .
В настоящее время мы делаем несколько проверок чисел и умножаем на 100 или 1 000 000, но обработка, выполняемая * запечатанной системой, может быть довольно дорогой при работе с большими числами, поэтому умножение всего на миллион просто ради Это действительно отличный вариант. В качестве приблизительного предположения скажем, что запечатанный алгоритм становится в 10 раз дороже каждый раз, когда вы умножаете в 10 раз.
Каков наиболее эффективный алгоритм, который также даст наилучший возможный результат для достижения того, что мне нужно, и есть ли математическое имя и / или формула для того, что мне нужно?
* Запечатанная система на самом деле не запечатана. Я владею / поддерживаю исходный код для него, но его 100 000 нечетных строк проприетарной магии, и он был тщательно проверен на наличие ошибок и производительности, и изменение его для работы с плавающими объектами не вариант по многим причинам. Это система, которая создает сетку из ячеек X по Y, затем в сетку сбрасываются тары, которые по X по Y, возникает «запатентованная магия» и результаты выплевываются - очевидно, это чрезвычайно упрощенная версия реальности, но это достаточно хорошее приближение.
Пока что есть несколько хороших ответов, и я подумал, как мне выбрать «правильный». Для начала я подумал, что единственный честный способ - это создать каждое решение и протестировать его, но позже я понял, что чистая скорость - не единственный важный фактор - более точное решение также очень важно. В любом случае, я написал тесты производительности, но в настоящее время я выбираю правильный ответ на основе скорости, а также точности, используя формулу «интуитивного ощущения».
Мои тесты производительности обрабатывают 1000 различных наборов из 100 случайно сгенерированных чисел.
Каждый алгоритм проверяется с использованием одного и того же набора случайных чисел.
Алгоритмы написаны на .Net 3.5 (хотя до сих пор совместим с 2.0)
Я очень старался сделать тесты максимально честными.
- Грег - Умножить на большое число
а затем разделить на GCD - 63
миллисекунды
- Энди - Разбор строк
- 199 миллисекунд
- Эрик - Decimal.GetBits - 160 миллисекунд
- Eric - двоичный поиск - 32
миллисекунды
- Има - извините, я не мог
выяснить, как реализовать свой
решение легко в .Net (я не
хочу потратить на это слишком долго)
- Билл - я полагаю, ваш ответ был довольно
близко к Грегу, так что не реализовали
Это. Я уверен, что это будет чуть-чуть быстрее
но потенциально менее точный.
Таким образом, решение Грега «Умножить на большое число, а затем разделить на GCD» было вторым самым быстрым алгоритмом, и оно дало самые точные результаты, поэтому сейчас я называю его правильным.
Я действительно хотел, чтобы решение Decimal.GetBits было самым быстрым, но оно было очень медленным, я не уверен, связано ли это с преобразованием двойного в десятичное или битовое маскирование и сдвиг. Там должно быть
похожее пригодное для использования решение для простого Double с использованием BitConverter.GetBytes и некоторыми знаниями, содержащимися здесь: http://blogs.msdn.com/bclteam/archive/2007/05/29/bcl-refresher-floating-point-types-the-good-the-bad-and-the-ugly-inbar-gazit-matthew-greig.aspx, но мои глаза просто продолжали стекаться каждый раз, когда я читал эту статью, и у меня, в конце концов, не хватало времени, чтобы попытаться реализовать решение .
Я всегда открыт для других решений, если кто-то может придумать что-то лучше.