Пожалуйста, прочитайте мои дополнительные информационные вопросы, но это один из способов, как я могу это сделать ..
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>
Тестовые сбои, потому что Вы достигли точности двоичного представления с плавающей точкой, которое является приблизительно 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
не достаточно точно для содержания десятичных разрядов, которые Вы ищете.
Как со всей арифметикой с плавающей точкой, Вы не должны проверять на равенство, а скорее что ошибка (эпсилон) является достаточно небольшой.
Если Вы заменяете:
return (d==check);
с чем-то как
return (Math.abs(d-check) <= 0.0000001);
это должно работать. Очевидно, эпсилон должен быть выбран, чтобы быть достаточно маленьким по сравнению с количеством десятичных чисел, на которые Вы проверяете.
Если Ваша цель состоит в том, чтобы представить число с точно n значащие цифры направо от десятичного числа, BigDecimal является классом для использования.
Неизменная, произвольная точность подписала десятичные числа. BigDecimal состоит из целого числа произвольной точности немасштабированное значение и 32-разрядный целочисленный масштаб. Если нуль или положительный, масштаб является количеством цифр направо от десятичной точки. Если отрицательный, немасштабированное значение числа умножается на десять к питанию отрицания масштаба. Значение числа, представленного BigDecimal, поэтому (unscaledValue ×, с 10 масштабами).
scale
может быть установлен через setScale (интервал)
double
тип является двоичным числом с плавающей точкой. Всегда существуют очевидные погрешности имея дело с ними, как будто они были десятичными числами с плавающей точкой. Я не знаю, что Вы будете когда-либо мочь записать свою функцию так, чтобы она работала способ, которым Вы хотите.
Необходимо будет, вероятно, вернуться к первоисточнику числа (строковый вход, возможно) и сохранить десятичное представление, если это важно для Вас.
Если можно переключиться на BigDecimal, то как Ken G объясняет, это - то, что необходимо использовать.
В противном случае затем необходимо иметь дело с хостом проблем, как упомянуто в других ответах. Мне Вы имеете дело с двоичным числом (дважды) и задаете вопрос о десятичном представлении того числа; т.е. Вы спрашиваете о Строке. Я думаю, что Ваша интуиция корректна.
Я не уверен, что это действительно выполнимо в целом. Например, сколько делают десятичные разряды 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;
}