2.9999999999999999>>.5?

UPDATE table1 t1
SET t1.value = 
    (select t2.CODE from table2 t2 
     where t1.value = t2.DESC) 
WHERE t1.UPDATETYPE='blah';
13
задан Jeff Atwood 10 October 2008 в 08:08
поделиться

10 ответов

На самом деле Вы просто заканчиваете тем, что делали пол () на первом операнде без любого операционного продолжения с плавающей точкой. Так как битовые операции сдвига влево и сдвига вправо только имеют смысл с целочисленными операндами, механизм JavaScript преобразовывает эти два операнда в целые числа сначала:

2.999999 >> 0.5

Становится:

Math.floor(2.999999) >> Math.floor(0.5)

, Который в свою очередь является:

2 >> 0

Смещение на средства на 0 битов "не делает сдвига", и поэтому Вы заканчиваете с первым операндом, просто усеченным к целому числу.

исходный код SpiderMonkey имеет:

switch (op) {
  case JSOP_LSH:
  case JSOP_RSH:
    if (!js_DoubleToECMAInt32(cx, d, &i)) // Same as Math.floor()
        return JS_FALSE;
    if (!js_DoubleToECMAInt32(cx, d2, &j)) // Same as Math.floor()
        return JS_FALSE;
    j &= 31;
    d = (op == JSOP_LSH) ? i << j : i >> j;
    break;

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

alert(2.999999999999999);

Вы доберетесь 2.999999999999999. Теперь попытайтесь добавить еще одни 9:

alert(2.9999999999999999);

Вы получите 3.

63
ответ дан 1 December 2019 в 17:10
поделиться

Это - возможно единственная худшая идея, которую я когда-либо видел. Его единственная возможная цель для существующего для победы в конкурсе кода obfusticated. Нет никакого значения для длинных чисел, которые Вы отправили - они - артефакт базовой реализации с плавающей точкой, проник, бог - знает сколько промежуточных слоев. Смещение бита дробным числом байтов безумно, и я удивлен, что оно не повышает исключение - но это - JavaScript, всегда готовый переопределять "безумный".

На вашем месте, я старался бы не когда-либо использовать эту "функцию". Его единственное значение как возможная первопричина для необычного состояния ошибки. Используйте Math.floor() и сжальтесь над следующим программистом, который поддержит код.

<час>

Подтверждение пары подозрений я имел при чтении вопроса:

  • смещение Права любой дробный номер x любым дробным номером y просто усечет x, давая тот же результат как Math.floor(), полностью смущая читателя.
  • 2.999999999999999777955395074968691915... просто наибольшее число, которое может дифференцироваться от "3". Попытайтесь оценить его отдельно - если Вы добавите что-нибудь к нему, это оценит к 3. Это - артефакт браузера и реализации локальной системы с плавающей точкой.
25
ответ дан 1 December 2019 в 17:10
поделиться

Если Вы хотите пойти глубже, считайте, "Что Каждый Программист Должен Знать Об Арифметике С плавающей точкой": http://docs.sun.com/source/806-3568/ncg_goldberg.html

6
ответ дан 1 December 2019 в 17:10
поделиться

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

В Chrome:

var x = 2.999999999999999777955395074968691915273666381835937499999;
var y = 2.9999999999999997779553950749686919152736663818359375;

document.write("x=" + x);
document.write(" y=" + y);

Распечатывает: x = 2,9999999999999996 y=3

5
ответ дан 1 December 2019 в 17:10
поделиться

Испытайте этот JavaScript: предупреждение (parseFloat ("2.9999999999999997779553950749686919152736663818359374999999"));

Тогда попытка это: предупреждение (parseFloat ("2.9999999999999997779553950749686919152736663818359375"));

то, Что Вы видите, является простой погрешностью с плавающей точкой. Для получения дополнительной информации об этом, посмотрите это, например: http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems .

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

Что касается того, почему правильное смещение на 0,5 делает что-либо нормальное вообще, кажется, что 0.5 просто самостоятельно преобразовывает в интервал (0) заранее. Тогда исходное плавание (2.999...) становится преобразованным в интервал усечением, как обычно.

5
ответ дан 1 December 2019 в 17:10
поделиться

Оператор права сдвига только воздействует на целые числа (обе стороны). Так, смещение прямо на.5 биты должно быть точно эквивалентно смещению прямо на 0 битов. И, левая сторона преобразовывается в целое число перед операцией сдвига, которая делает то же самое как Math.floor ().

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

я подозреваю, что преобразование 2.9999999999999997779553950749686919152736663818359374999999 к он - двоичное представление, было бы поучительно. Это - вероятно, только 1 бит, отличающийся от истинных 3.

Хорошее предположение, но никакая сигара. Поскольку число FP двойной точности имеет 53 бита, последнее число FP, прежде чем 3 будет на самом деле (точно): 2.999999999999999555910790149937383830547332763671875

, Но почему это 2.9999999999999997779553950749686919152736663818359375

(и это точно, не 49999...!)

, который является выше , чем последняя визуализуемая единица? Округление. Подпрограмма преобразования (Строка к числу) просто правильно программируется к раунду вход следующее число с плавающей точкой.

2.999999999999999555910790149937383830547332763671875

....... (значения между, увеличиваясь)-> округляют в меньшую сторону

2.9999999999999997779553950749686919152736663818359375

....... (значения между, увеличиваясь)-> окружают к 3

3

, вход преобразования должен использовать полную точность. Если число является точно половиной между теми двумя fp числами (который является 2.9999999999999997779553950749686919152736663818359375), округление зависит от флагов setted. Значение по умолчанию, округляющееся, кругло к даже, означая, что число будет округлено к следующему четному числу.

Теперь

3 = 11. (двоичный файл)

2.999... = 10.11111111111...... (двоичный файл)

Все биты установлены, число всегда нечетно. Это означает, что точная половина числа будет окружена, таким образом, Вы получите странное..... 49 999 периодов, потому что это должно быть меньше, чем точная половина, чтобы быть различимым от 3.

2
ответ дан 1 December 2019 в 17:10
поделиться

Я подозреваю, что преобразование 2.9999999999999997779553950749686919152736663818359374999999 к его двоичному представлению было бы поучительно. Это - вероятно, только 1 бит, отличающийся от истинных 3.

2
ответ дан 1 December 2019 в 17:10
поделиться

И добавить к ответу John's, разногласия этого являющегося более производительным, чем Math.floor являются очень маленькими.

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

1
ответ дан 1 December 2019 в 17:10
поделиться

Нужно отметить, что номер ".0000000000000007779553950749686919152736663818359374" вполне возможно Эпсилон , определен как "самый маленький номер E, таким образом что (1+E)> 1".

1
ответ дан 1 December 2019 в 17:10
поделиться
Другие вопросы по тегам:

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