Как проверить, имеет ли двойное в большинстве n десятичных разрядов?

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

console.clear();

var $fakeAsync = function (api, result) {
    var isEmptyCall = _.isNull(api) || api.length === 0;
    dfd = $.Deferred(function () {
        setTimeout(function () {
            dfd.resolve(isEmptyCall ? null : result);
        }, isEmptyCall ? 0 : 50);
    });
    return dfd.promise();
};
var $fakeData = [
	{Id: 1, Name: 'foo', UserStatus: 1000},
  {Id: 2, Name: 'bar', UserStatus: 1001},
  {Id: 3, Name: 'stack', UserStatus: 1000},
  {Id: 4, Name: 'overflow', UserStatus: 1002}
]
var $fakeUserStates = {
	1000: 'pending',
  1001: 'ready',
  1002: 'cancelled',
  1003: 'banned'
};

function MyViewModel() {
	var self = this;
  
  self.userStates = [];
  
  self.loadMapping = function () {
  	return $fakeAsync('api/fakemappingcall', $fakeUserStates).done(function (result) {
    console.log('mapping gathered');
    	self.userStates = result;
    });
  };
  
  self.loadData = function () {
  	return $fakeAsync('api/fakedatacall', $fakeData);
  };
  
  self.method = function () {
  	self.loadData().done(function (result){
      _.each(result, function (r) { _.extend(r, { 'UserStatusText': self.userStates[r['UserStatus']] }) });
      console.log(result);
    });
  };
  
  self.loadMapping().done(function () {
  	self.method();
  });
};

ko.applyBindings(new MyViewModel());
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>

10
задан Turismo 7 November 2008 в 08:06
поделиться

6 ответов

Тестовые сбои, потому что Вы достигли точности двоичного представления с плавающей точкой, которое является приблизительно 16 цифрами с двойной точностью IEEE754. Умножение на 649632196443.4279 на 10000 усечет двоичное представление, ведя к ошибкам при округлении и делении впоследствии, таким образом, лишении законной силы результата функции полностью.

Для получения дополнительной информации см. http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems

Лучший путь состоял бы в том, чтобы проверить ли n+1 десятичные разряды ниже определенного порога. Если d - round(d) меньше, чем epsilon (см. предел), десятичное представление d не имеет никаких значительных десятичных разрядов. Так же, если (d - round(d)) * 10^n меньше, чем epsilon, d может иметь самое большее n значительные места.

Используйте стрельбу по тарелочкам Jon DoubleConverter проверять на случаи где d не достаточно точно для содержания десятичных разрядов, которые Вы ищете.

6
ответ дан 3 December 2019 в 21:24
поделиться

Как со всей арифметикой с плавающей точкой, Вы не должны проверять на равенство, а скорее что ошибка (эпсилон) является достаточно небольшой.

Если Вы заменяете:

return (d==check);

с чем-то как

return (Math.abs(d-check) <= 0.0000001);

это должно работать. Очевидно, эпсилон должен быть выбран, чтобы быть достаточно маленьким по сравнению с количеством десятичных чисел, на которые Вы проверяете.

3
ответ дан 3 December 2019 в 21:24
поделиться

Если Ваша цель состоит в том, чтобы представить число с точно n значащие цифры направо от десятичного числа, BigDecimal является классом для использования.

Неизменная, произвольная точность подписала десятичные числа. BigDecimal состоит из целого числа произвольной точности немасштабированное значение и 32-разрядный целочисленный масштаб. Если нуль или положительный, масштаб является количеством цифр направо от десятичной точки. Если отрицательный, немасштабированное значение числа умножается на десять к питанию отрицания масштаба. Значение числа, представленного BigDecimal, поэтому (unscaledValue ×, с 10 масштабами).

scale может быть установлен через setScale (интервал)

6
ответ дан 3 December 2019 в 21:24
поделиться

double тип является двоичным числом с плавающей точкой. Всегда существуют очевидные погрешности имея дело с ними, как будто они были десятичными числами с плавающей точкой. Я не знаю, что Вы будете когда-либо мочь записать свою функцию так, чтобы она работала способ, которым Вы хотите.

Необходимо будет, вероятно, вернуться к первоисточнику числа (строковый вход, возможно) и сохранить десятичное представление, если это важно для Вас.

1
ответ дан 3 December 2019 в 21:24
поделиться

Если можно переключиться на BigDecimal, то как Ken G объясняет, это - то, что необходимо использовать.

В противном случае затем необходимо иметь дело с хостом проблем, как упомянуто в других ответах. Мне Вы имеете дело с двоичным числом (дважды) и задаете вопрос о десятичном представлении того числа; т.е. Вы спрашиваете о Строке. Я думаю, что Ваша интуиция корректна.

1
ответ дан 3 December 2019 в 21:24
поделиться

Я не уверен, что это действительно выполнимо в целом. Например, сколько делают десятичные разряды 1.0e-13 имейте? Что, если это следовало из некоторой погрешности округления при выполнении арифметики и действительно справедливо 0 скрытый? Если включенный, другая рука Вы спрашиваете, существуют ли какие-либо ненулевые цифры в первых n десятичных разрядах, можно сделать что-то как:

   static boolean checkDecimalPlaces(double d, unsigned int decimalPlaces){
      // take advantage of truncation, may need to use BigInt here
      // depending on your range
      double d_abs = Math.abs(d);
      unsigned long d_i = d_abs; 
      unsigned long e = (d_abs - d_i) * Math.pow(10, decimalPlaces);
      return e > 0;
   }
0
ответ дан 3 December 2019 в 21:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: