Подтвердить что ты не робот

Понимание переменных с плавающей запятой

Есть некоторая проблема, я все равно не понимаю.

посмотрите этот код, пожалуйста,


<script type="text/javascript">
function math(x)
{
 var y;
 y = x*10;
 alert(y);
}

</script>
<input type="button" onclick="math(0.011)">

Что нужно предупредить после нажатия кнопки? я думаю 0.11, но нет, он предупреждает 0,10999999999999999 объясните пожалуйста это поведение. заранее спасибо

4b9b3361

Ответ 1

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

что вам нужно сделать, это форматировать это число.

см. это java объяснение, которое также применимо здесь, если вы хотите знать , почему это происходит.

в javascript все числа представлены как 64-битные поплавки, поэтому вы часто сталкиваетесь с такими вещами.

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

Ответ 2

Ok. Позвольте мне попытаться объяснить это.

Основная вещь, которую нужно помнить с помощью чисел с плавающей запятой, такова: они занимают ограниченное количество бит и пытаются представить исходное число с использованием арифметики base-2.

Как вы знаете, в базовых 2 арифметических целых числах представлены степени 2, которые они содержат. Таким образом, 6 будет представлено как 4 + 2, т.е. в двоичном формате 110.

Чтобы понять, как представлены дробные числа, вам нужно подумать о том, как мы представляем дробные числа в нашей десятичной системе. Дробная часть чисел (например, 0.11) представлена ​​в виде кратных обратных степеней 10 (так как основание равно 10). Таким образом, 0.11 фактически составляет 1/10 + 1/100. Как вы понимаете, это недостаточно мощно, чтобы представлять все дробные числа в ограниченном количестве цифр. Например, 1/3 будет 0,333333.... в бесконечном порядке. Если бы у нас было всего 32 цифры пробела, чтобы записать число вниз, мы получим только приблизительное значение к исходному числу, 0.3333333333333333333333333333333333. Это число, например, дало бы 0.9999999999999999999999999999999999, если бы оно было умножено на 3, а не 1, как вы ожидали.

Ситуация аналогична в базе-2. Каждое дробное число будет представлено как кратность обратных степеней 2. Таким образом, 0,75 (в десятичной форме) (т.е. 3/4) будет представлено как 1/2 + 1/4, что будет означать 0.11 (в базе-2). Так же, как база 10 не может достаточно представить каждое дробное число конечным образом, base-2 не может представлять все дробные числа при ограниченном пространстве.

Теперь попробуйте представить 0.11 в базе-2; вы начинаете с 11/100 и пытаетесь найти обратную мощность 2, которая меньше этого числа. 1/2 не работает, 1/4 ни, ни 1/8. 1/16 подходит для счета, поэтому вы отмечаете 1 на 4-м месте после десятичной точки и вычитаете 1/16 из 11/100, Осталось 19/400. Теперь попробуйте найти следующую мощность 2, которая соответствует описанию. 1/32 кажется тем, что отметьте 5-е место после точки и вычтите 1/32 от 19/400, вы получите 13/800. Следующий - 1/64, и вы остаетесь с 1/1600, а следующая - на уровне 1/2048 и т.д. и т.д. Таким образом, мы получили до 0.00011100001, но он продолжается и продолжается; и вы увидите, что всегда остается остаток. Теперь я не прошел весь расчет, но после того, как вы поместили 32 бинарных цифры после точки, вы, вероятно, по-прежнему будете иметь некоторую долю слева (и это предполагает, что все 32 бита пространства расходуются, представляя десятичную часть, которой это не так). Таким образом, я уверен, что вы можете понять, что итоговое число может отличаться от его фактического значения на некоторую величину.

В вашем случае разница составляет 0,00000000000000001, что составляет 1/100000000000000000 = 1/10 ^ 17, и я уверен, что вы можете понять, почему у вас может быть это.

Ответ 3

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

Примечание: Если вы показываете значение x, оно все равно показывает 0.011, потому что JavaScript еще не решил, какой тип переменной x имеет. Но после его умножения на 10 тип получил значение с плавающей запятой (это единственная возможность), и отображается круглая ошибка.

Ответ 4

Вы можете попытаться исправить nr из десятичных знаков с помощью этого:

// fl is a float number with some nr of decimals
// d is how many decimals you want
function dec(fl, d) {
  var p = Math.pow(10, d);
  return Math.round(fl*p)/p;
}

Пример:

var n = 0.0012345;
console.log(dec(n,6)); // 0.001235
console.log(dec(n,5)); // 0.00123
console.log(dec(n,4)); // 0.0012
console.log(dec(n,3)); // 0.001

Он работает, сначала умножая float с 10^3 (1000) на три десятичных знака, или 10^2 (100) на два десятичных знака. Затем сделайте раунд и разделите его на первоначальный размер.
Math.pow(10, d) делает 10^d (означает, что d даст нам 1000).

В вашем случае do alert(dec(y,2));, он должен работать.