Округление элементов формулы вверх/вниз до получения целого числа

Я хочу округлить вверх или вниз a, пока результат не станет целым числом.

a = 1.2
b = 1.5
a*b*16 = 28.8

Однако у меня есть критерий: a должно быть зафиксировано не более чем с 3 знаками после запятой. Поэтому мне нужен расчет, в котором приведенный выше пример будет выводиться следующим образом:

a = 1.25
b = 1.5
a*b*16 = 30

На самом деле я что-то кодирую на Sass, но если бы кто-нибудь мог указать мне правильное направление, будь то написанное на JavaScript или что-то еще. Мне просто нужна помощь в формулировке этого запутанного вычисления!

Критерии: a должно содержать не более 3 знаков после запятой. the result должно быть целым числом.

Это вообще возможно?


person Community    schedule 19.05.2012    source источник
comment
Определить фиксированное число?   -  person Madara's Ghost    schedule 20.05.2012
comment
Без десятичных знаков. Целое число :)   -  person    schedule 20.05.2012
comment
1,25 и 1,5 не являются целыми числами.   -  person Madara's Ghost    schedule 20.05.2012
comment
Это смущает. 16 это константа? В переменная? Б тоже 3 уб. мест или меньше?   -  person Tina CG Hoehr    schedule 20.05.2012
comment
Результат должен быть целым числом. a необходимо исправить. Я обновил свой пост, чтобы сделать это более понятным. Да, 16 - это константа. b и 16 произвольны.   -  person    schedule 20.05.2012
comment
Как округлить число до нужных мест: jsfiddle.net/DerekL/tmUqR   -  person Derek 朕會功夫    schedule 20.05.2012


Ответы (2)


Вы не можете гарантировать, что результатом будет целое число, если вы ограничите точность переменных, независимо от того, какой метод вы используете.

Примеры:

  • Если b = 3, то a = 30/(16 3) = 30/48 = 5/8 = 0,625
    В этом случае 0,625 3 16 = 30 точно.

  • Если b = 7, то a = 30 / (16 7) = 30/112 = 15/56 = 0,267857...
    Округление a дает 0,268, а 0,268 7 16 = 30,016, что является ближайшим возможным приближением до 30. Другими словами, не существует значения a, удовлетворяющего критериям, и 0,268 — это лучшее, что вы можете сделать.

Но вы можете подобрать наилучшее значение, чтобы результат был как можно ближе к целому числу.

Решите уравнение для нужной переменной, затем округлите до соответствующего числа десятичных знаков.

a = 30. / (16. * b); // true value
a = ((int) (1000 * a + 0.5)) / 1000; // round to 3 decimals

Большинство современных языков предоставляют библиотечные функции для округления за вас; Я написал это «от руки», чтобы вы могли понять, как это работает.

person Adam Liss    schedule 19.05.2012
comment
Хм… но если я округлю a, то вычисление больше не приведет к нужному целому числу. - person ; 20.05.2012
comment
Что, если… я сделал цикл, чтобы найти все возможные переменные, у которых не более 3 знаков после запятой, а затем использовал ближайший результат? Это работает у меня в голове… понятия не имею, как бы я это закодировал. - person ; 20.05.2012
comment
См. мой комментарий к одному из других ответов: цикл просто использует метод проб и ошибок, чтобы найти результат, заданный этой формулой. Это все равно, что сказать: я недостаточно знаю математику (или слишком ленив), чтобы найти ответ, поэтому я буду пробовать все возможные комбинации, пока не найду ту, которая мне понравится. Некоторые проблемы должны решаться методом проб и ошибок, поскольку решения в закрытой форме не существует. Это не один из них. - person Adam Liss; 20.05.2012
comment
Спасибо за отличное объяснение. Однако, учитывая критерии этой формулы, конечно, метод проб и ошибок — единственное решение? Если нет формулы, которая может это сделать. Я понимаю, что метод, который вы предоставляете, даст максимально возможное целое число, но это критерий. Это должно быть целое число (не спрашивайте, что я делаю, это связано с пикселями и прочим!) - person ; 20.05.2012
comment
Попробуйте оба способа. Вы обнаружите, что пришли к тому же ответу. Мой первый пример показывает, что произойдет, если точное решение существует: формула вычислит его (и метод проб и ошибок найдет его). Второй показывает, что происходит, если нет: формула находит значение a, которое ближе всего к получению целого числа (и метод проб и ошибок просто не увенчается успехом). Вы не можете нарушить законы математики, просто задавая вопрос снова и снова и надеясь получить другой ответ. :-( - person Adam Liss; 20.05.2012
comment
Я полагаю, что окончательное решение здесь состоит в том, чтобы использовать пробы и ошибки, но с ограничениями. Если ответ не может быть найден реалистично, то я должен предоставить запасной вариант в своем коде. Большое спасибо за вашу помощь. - person ; 20.05.2012
comment
Вы все еще, кажется, упускаете суть. Если решение существует, то метод проб и ошибок даст вам тот же результат, что и формула, но займет больше времени. Если решения не существует, формула обеспечит наилучшее решение и цикл проб и ошибок никогда не прекратится. Опять же, я настоятельно предлагаю вы пытаетесь решать обеими способами, пока не поймете это. - person Adam Liss; 20.05.2012
comment
Я пытаюсь понять ваше объяснение. Это не ты, это я! Моя математика не очень. Думаю, я понимаю, о чем вы говорите, но в ваших расчетах результат (30) кажется константой. По сути, мне нужен способ сказать это: эй, у меня есть одна переменная (1.2) и две константы (1.5 и 16). Умножьте эти числа и дайте мне целое число, но если вам нужно изменить переменную, вы можете… просто не более чем до 3 знаков после запятой. - person ; 20.05.2012
comment
@OliverJosephAsh: Значит, b теперь константа?! В этом случае у вас есть результат, две константы и переменная. Результат зависит только от переменной. Таким образом, вы можете вернуться назад и вычислить переменную по результату (как сказал Адам). - person Andrew Leach; 20.05.2012
comment
Помните, что результат тоже своего рода переменная. Цель состоит в том, чтобы найти наилучшее совпадение, где результат является целым числом, а переменная имеет не более 3 знаков после запятой. Клянусь, метод проб и ошибок — единственный способ сделать это. - person ; 20.05.2012

i = Math.round(a*b*16);
a = i/b/16;
a = a.toFixed(2);
b = i/16/a;

тест om i==a*b*16

person hpekristiansen    schedule 19.05.2012