Как округлить десятичную дробь до ближайшей дроби? - PullRequest
7 голосов
/ 02 октября 2009

Не уверен, правильно ли это задавать, или нет, но в этом-то и проблема.

Учитывая широту 26,746346081599476, как мне найти число 26,75 как 16-е больше, чем число и 26,6875 как 16-е меньше, чем число?

26.0
26.0625
26.125
26.1875
26.25
26.3125
26.375
26.4375
26.5
26.5625
26.625
26.6875
My Number: 26.746346081599476
26.75
26.8125
26.875
26.9375
27.0

Я использую JavaScript, поэтому ответ на него будет полезным, но не обязательным. Я мог бы перебор, но я ищу элегантный способ сделать это.

В целом я хочу создать стандартные листы для картографического приложения, над которым я работаю. Мы используем карты Bing, и я загружаю данные по требованию, каждый раз, когда пользователь выполняет панорамирование или увеличение. Было бы неплохо воспользоваться кэшированием на стороне сервера для этих запросов, поэтому, если я стандартизирую запросы, отправленные на сервер, я получу некоторые попадания в кеш. Если я не стандартизирую запросы к серверу, маловероятно, что один и тот же пользователь будет одновременно просматривать точное местоположение.

Так что вероятность попадания в кеш выше: /path/data.json?tl=26.6875,-80.6875&br=26.75,-80.75 чем с: /path/data.json?tl=26.74946187679896,-80.10930061340332&br=26.743234270702878,-80.09607195854187

Любые нестандартные ответы также приветствуются.

Ответы [ 6 ]

14 голосов
/ 02 октября 2009

Чтобы найти ближайшие кратные 1 / n:

lower_bound = 1.0 / n * Math.floor(n * your_number);
upper_bound = 1.0 / n * Math.ceil(n * your_number);

Возможно, вы захотите использовать специальную обработку, если ваш номер уже кратен 1/16.

// alternate solution so that lower_bound <= your_number < upper_bound
lower_bound = 1.0 / n * Math.floor(n * your_number);
upper_bound = 1.0 / n * Math.floor(n * your_number + 1.0);
9 голосов
/ 02 октября 2009

Вы умножаете значение на 16, используете метод floor или ceil и делите на 16:

var higher = Math.ceil(number * 16) / 16;
var lower = Math.floor(number * 16) / 16;
2 голосов
/ 02 октября 2009
function bounds(number, numerator, denominator) {
  var frac = denominator/numerator;
  return {
    lower: Math.floor(frac * number) / frac,
    upper: Math.ceil(frac * number) / frac,
  }
} 


bounds(26.746346081599476,1,16)
// returns an object with properties
// lower : 26.6875 
// upper : 26.75
1 голос
/ 02 октября 2009

Звучит как округление до 16-го числа ...

rounded = Math.round(number * 16) / 16;

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

0 голосов
/ 02 октября 2009

Пара стратегий, которые еще не опубликованы:

A) создать таблицу поиска, которая отображает цифры после десятичной дроби с точностью до 16-го числа. Просто используйте ту точность, которая вам нужна (вероятно, сотые доли).

B) создать таблицу всех 16-ых чисел от 0 до 1 и выполнить поиск в двоичном стиле с вашим номером% 1.

0 голосов
/ 02 октября 2009

Каких наименьших фракций вы хотите разделить? IE 16 будут самыми маленькими приращениями?

Если да, просто умножьте свое число на 16. Сократите его до целого и разделите на 16, чтобы найти нижнюю границу. Обрежьте его до типа int, добавьте 1, а затем разделите на 16, чтобы найти верхнюю границу.

...