Java: приращение через Float.floatToIntBits? - PullRequest
3 голосов
/ 29 марта 2012

Мне нужно увеличить значение с плавающей точкой атомарно. Я получаю значение int, вызывая Float.floatToIntBits для него. Если я просто сделаю i ++ и преобразую его обратно в float, он не даст мне ожидаемого значения. Так как бы я поступил об этом?

(я пытаюсь создать AtomicFloat через AtomicInteger, отсюда и этот вопрос).

РЕДАКТИРОВАТЬ: вот что я сделал:

Float f = 1.25f;
int i = Float.floatToIntBits(f);
i++;
f = Float.intBitsToFloat(i);

Я хотел 2,25, но вместо этого получил 1,2500001.

Ответы [ 2 ]

5 голосов
/ 29 марта 2012

Причина в том, что биты, которые вы получаете от floatToIntBits, представляют

  1. знак
  2. Показатель
  3. мантисса

выложено так:

Repr:  Sign   Exponent          Mantissa
Bit:    31   30......23  22.....................0

Увеличение целого числа, хранящего эти поля на 1, не увеличит значение с плавающей запятой, которое оно представляет, на 1.

Я пытаюсь создать AtomicFloat через AtomicInteger, поэтому этот вопрос

Я сделал именно это в ответ на этот вопрос:

Чтобы добавить функциональность для увеличения числа на единицу, вы можете скопировать код incrementAndGet с AtomicInteger (и изменить с int на float):

public final float incrementAndGet() {
    for (;;) {
        float current = get();
        float next = current + 1;
        if (compareAndSet(current, next))
            return next;
    }
}

(Обратите внимание, что если вы хотите увеличить число с плавающей запятой на наименьшее возможное значение , вы берете вышеуказанный код и меняете current + 1 на current +Math.ulp(current).)

2 голосов
/ 29 марта 2012

Часть atomic может быть реализована поверх compareAndSet для класса-оболочки, как показано в ссылке aioobe.Операторы приращения AtomicInteger реализованы следующим образом.

Часть increment - это совершенно другая проблема.В зависимости от того, что вы подразумеваете под «увеличить число с плавающей запятой», требуется либо добавить один к числу, либо увеличить его на единицу ULP .Для последнего, в Java 6, метод Math.nextUp - это то, что вы ищете.Для уменьшения на один ULP полезен метод Math.nextAfter .

...