2009-08-19 2 views
4

У меня сложный математический вопрос, который разбивает мой мозг, мою доску и все мои ручки. Я работаю с файлом, который выражает 2 значения, multipicand и Процент. Оба эти значения должны быть целыми числами. Эти два значения умножаются вместе для получения диапазона . Диапазон - это значение поплавка.Вывести целочисленные коэффициенты поплавкового значения?

Мои пользователи редактируют диапазон, и мне нужно рассчитать новый процент и значение мультипликатора. Еще не запутались? Ниже приведен пример:

 
    Multiplicand: 25000 Apples 
    Percentage: 400 (This works out to .4% or .004) 
    Range: 100.0 Apples (Calculated by Multiplicand * Percentage) 

Чтобы усложнить ситуацию, допустимые значения для процента составляют 0-100000. (Значение 0-100%) Multiplicand - это значение от 1 до 32 бит int max (предположительно без знака).

Мне нужно, чтобы для пользователей, чтобы ввести диапазон, например, так:

Range: .04 Apples 

и рассчитать соответствующий процент и множимое. Используя первый пример:

 
    OriginalMultiplicand: 25000 Apples 
    OriginalPercentage: 400 (This works out to .4% or .004) 
    OriginalRange: 100.0 Apples (Calculated by Multiplicand * Percentage) 
    NewRange: .01 Apples 
    NewPercentage: 40 
    NewMultiplicand: 25 Apples 

Расчет пример легко, все, что требовалось регулировал вниз множимое и процент вниз масштабного фактора нового и старого диапазона. Проблема возникает, когда пользователь меняет значение примерно на 1400.00555. Внезапно у меня нет чистого способа настроить два значения.

Мне нужен алгоритмический подход для получения значений для M & P, которые производят максимально возможное значение в желаемом диапазоне. Какие-либо предложения?

+0

Действительно ли пользователи будут вводить значение, равное 1400.00555, или это артефакт неточности поплавка? Существуют ли какие-либо правила относительно того, как вы настраиваете Multiplicand и Percentage, чтобы соответствовать вновь введенному диапазону, то есть если Range теперь равен 6, имеет ли значение, если Multiplicand равен 2, а Percentage - 3 или наоборот? –

+0

Название несколько вводит в заблуждение, поскольку ваш процент не является ДЕЙСТВИТЕЛЬНО целым числом, это десятичное значение, представленное как целое число (предположительно, чтобы облегчить его хранение) –

+0

Хотя пользователи могут не вводить 1400.00555, я мог бы легко увидеть их ввод что-то вроде 133.33333333333333333333333. Нет правил относительно Multiplicand и Percentage, если диапазон правильный. Процент используется как номер фиксированной точки в моем коде, но он представлен как целое число. – 2009-08-19 22:32:34

ответ

1

Чтобы увеличить количество сохраненных десятичных точек, вы должны использовать P из 1 или 0,1%. Если переливается М, то увеличиваем P.

Так для примера 1400.00555, Р 1 и М 1400006

Ваш алгоритм будет искать самой низкой Р, что М не переполнения. И вы можете сделать двоичный поиск здесь.

public int binarySearch(int P0, int P1) { 
    P = (P1 - P0)/2; 
    if(P == P0) { 
    if(R/(P0/100f) does not overflows 32-bit int) { 
     return P0; 
    } else { 
     return P1; 
    } 
    } 
    if(R/(P/100f) does not overflows 32-bit int) { 
    return binarySearch(P0, P); 
    } else { 
    return binarSearch(P, P1); 
    } 
} 

P = binarySearch(1, 100000); 
M = round(R/(P/100f)); 
+0

Это довольно близко к решению, которое я использовал. Я приступил к настройке P up и M down, когда это было возможно, просто для того, чтобы сохранить ценности понятными человеку, но в остальном я сделал это в основном. – 2009-08-20 15:24:25

0

Как я понимаю из вашего примера, вы можете представить range в 100000 разных multiplicand * percentage. любой выбор multiplicand даст вам удовлетворительное значение процента и наоборот. Таким образом, у вас есть это уравнение с двумя переменными:

Multiplicand * Percentage = 100.0 

Вы должны выяснить еще одно уравнение (ограничение), чтобы получить конкретное значение Multiplicand ИЛИ Percentage для решения этого уравнения. В противном случае вы можете выбрать Процент для любого числа между 0-100000 и просто подставить его в первом уравнении, чтобы получить значение Multiplicand. Я надеюсь, что я правильно понял вопрос :)


Edit: ОК, то вы должны Факторизуем диапазон легко. Получите range, затем попробуйте разложить его, разделив диапазон на percentage(2-100000). Когда напоминание о делении равно нулю, вы получили факторы. Это быстрый псевдо-код:

get range; 
percentage = 2; 
while(range % percentage != 0) 
{ 
    percentage++; 
} 

multiplicand = range/percentage; 

Все, что вы должны сделать сейчас, чтобы рассчитать свои пределы:

max of percentage = 100000; 
max of multiplicand = 4294967295; 

Max of range = 4294967295 * 100000 = 429496729500000 (15-digit); 

ваш диапазон Макс состоит из 15 цифр на максимуме. double типы данных в большинстве языков программирования can представляют его. Делайте расчет с использованием doubles и просто конвертируйте Multiplicand & Percentage в int в конце.

+0

Ты сделал, я думаю. Однако я должен гарантировать, что оба значения являются целыми числами. Например, я не могу предположить, что процент равен 50000, так как это может привести к нечетному умножению. – 2009-08-19 22:36:08

0

у вас есть

1) M * P = A 

то есть второе значение для А, так и новые значения M и P, назовём затем M2, P2 и A2:

2) M2 * P2 = A2 

Это я не знаю точно, но это то, что вы, кажется, говорят имхо: соотношение должно остаться то же самое, то

3) M/P = M2/P2 

Теперь у нас есть 3 фас ations и 2 неизвестных М2 и Р2


Один из способов решить эту проблему:

3) становится

M/P = M2/P2 
=>M2 = (M/P)*P2 

чем заменитель, что в 2)

(M/P)*P2*P2 = A2 
=> P2*P2 = A2 * (P/M) 
=> P2 = sqrt(A2 * (P/M)) 

поэтому сначала решить P2, то M2, если я не совершал ошибок

Должно быть какое-то округление, если M2 и P2 должны быть целыми.

EDIT: я забыл о целочисленном процент, так сказать

P = percentage/100000 or P*100000 = percentage 
P2 = percentage2/100000 or P2*100000 = percentage2 

так просто решить для Р2 и М2, и умножать P2 с 100000

+0

К сожалению, это не гарантирует мне два целочисленных значения для M2 и P2. – 2009-08-19 22:42:02

+0

, так что любые 2 значения будут делать, если они целые? –

+0

iF вы хотите получить ближайшее значение, вы получите синтаксический анализ от double до int в некоторой точке для приближения –

0

(у меня был плохой метод здесь, но я стер это потому, что она сосала)

EDIT:.

Там должен быть лучше, чем это. Давайте перефразируем проблему:

У вас есть произвольное число с плавающей запятой. Вы хотите представить это число с плавающей запятой двумя целыми числами. Целочисленные числа, умноженные вместе, а затем деленные на 100000,0, равны числу с плавающей запятой. Единственное другое ограничение состоит в том, что одно из целых чисел должно быть равно или меньше 100000.

Понятно, что вы не можете точно представлять числа с плавающей запятой точно. Фактически, вы можете ТОЛЬКО представлять числа, которые четко выражены в 1/100000s, даже если вы имеете бесконечное количество цифр точности в «multipicand». Вы можете точно представлять 333.33333, с 33333333 как одно число и 1 как другое; вы просто не можете получить больше 3s.

Учитывая это ограничение, я думаю, что вам лучше всего следующее:

  1. Умножьте ваш поплавок на 100000 в целочисленном формате, возможно длительное или какой-то вариант BigNumber.
  2. Фактор. Запишите все факторы. Неважно, сохраните ли вы их как 2^3 или 2 * 2 * 2 или что.
  3. Захватите столько факторов, сколько сможете, без их умножения на 100000. Это станет вашим процентом. (Не пытайтесь делать это идеально, найти оптимальное решение является NP-трудной проблемой.)
  4. Возьмите остальные факторы и умножьте их вместе. Это твой мультипликат.
+0

Если это правильная постановка задачи, то просто умножьте число с плавающей запятой на 100000, тогда округленное целочисленное значение будет мультипликатором и процент всегда 1 :) –

0

Кажется, что вы хотите выбрать M и P такая, что R = (M * P)/100000. Так M * P = 100000 * R, где вы должны обогнуть правую Ань целое число.

Я бы умножил диапазон на 100000, а затем выберем M и P как факторы результата, чтобы они не переполняли их допустимые диапазоны.

Смежные вопросы