Как сопоставить двойное значение с плавающим в Java?

На первый взгляд мой вопрос может показаться немного странным; но приведение двойного значения к значению с плавающей запятой - это не то, что я хочу. Поскольку, когда вы его используете, вы просто теряете некоторую точность по отношению к правилам, определенным IEEE-754, и не можете добиться фактического сопоставления двойного значения с диапазоном с плавающей запятой; это бесполезно. Следующее выражение работает, но оно очень дорого, когда у вас есть большое количество входных данных:

float mappedVal = (float)((val * MAX_FLOAT_VALUE + 1) / MAX_DOUBLE_VALUE);

Могу ли я приблизить результат к упомянутому выше «mappedVal» с помощью каких-то побитовых операций, чтобы ускорить те же самые вычисления?


person iliTheFallen    schedule 15.03.2013    source источник
comment
пожалуйста, приведите примеры входных и выходных данных   -  person Nikolay Kuznetsov    schedule 15.03.2013
comment
Вы говорите, что поскольку приведение теряет точность по отношению к IEEE-754, оно бесполезно. Тогда вы спрашиваете о побитовых операциях для аппроксимации результата? Просто бросьте это, если вы хотите приближение.   -  person mjuarez    schedule 15.03.2013
comment
Только догадываюсь, но я думаю, что это будет недолив   -  person Bohemian♦    schedule 15.03.2013
comment
Ok. например, всякий раз, когда у вас есть двойное значение, превышающее значение MAX_FLOAT, и вы приводите его, выполняя инструкцию типа float mappValue = (float)myDoubleValue;; округляется до значения MAX_FLOAT; то есть точно равняется значению MAX_FLOAT. Это не отображение; но только приближение.   -  person iliTheFallen    schedule 15.03.2013
comment
Является ли MAX_FLOAT_VALUE равным Float.MAX_VALUE и MAX_FLOAT_VALUE равным Double.MAX_VALUE? Актерского состава все еще не хватает? Он проверяет ваше выражение при этих предположениях для val == 1: результат равен 0.   -  person Claude    schedule 15.03.2013
comment
Да; MAX_FLOAT_VALUE = Float.MAX_VALUE и MAX_DOUBLE_VALUE = Double.MAX_VALUE. ааа да, вы также правы в том, что есть явное приведение выражения правой части к float. Я только что исправил это; спасибо за поправку!   -  person iliTheFallen    schedule 15.03.2013
comment
Является ли ваш вопрос приведенным выше сопоставлением заменой приведения или как ускорить приведенное выше выражение? Для ускорения вы можете предварительно вычислить 1/MAX_DOUBLE_VALUE и MAX_FLOAT_VALUE/MAX_DOUBLE_VALUE.   -  person Claude    schedule 15.03.2013
comment
Можете ли вы указать, какое отображение вы хотите? Поскольку существует (намного) больше двойников, чем поплавков, вам придется принять, что многие двойники сопоставляются с одним и тем же поплавком, какое правило вы хотите применить? Если, то есть, это не приведение типов.   -  person High Performance Mark    schedule 15.03.2013
comment
Я не понимаю вопроса. Вы хотите преобразовать двойное число в число с плавающей запятой, но не хотите потери точности, которая неизбежно влечет за собой? Не настоящий вопрос.   -  person user207421    schedule 15.03.2013
comment
Да да! именно я хочу сопоставить некоторые из двойников с одним и тем же значением с плавающей запятой! Это как в opengl, например, вы сопоставляете (скажем) целочисленное значение с диапазоном [-1.0, 1.0] с помощью (2*val + 1)/MAX_INTEGER_VALUE. На самом деле, мой случай очень похож на тот!   -  person iliTheFallen    schedule 15.03.2013
comment
float значения не могут представлять все те же значения, что и double значения. Это математически невозможно, так как float имеет меньше битов. Следовательно, вы должны потерять информацию. Теоретически возможны многие преобразования. Некоторые сохранят точность в определенном диапазоне, но будут очень неточными за его пределами, некоторые изменят динамический диапазон, но сильно потеряют в точности и так далее. Чтобы получить ответ, вам необходимо указать характеристики желаемого преобразования.   -  person Eric Postpischil    schedule 15.03.2013
comment
Двойное значение находится в диапазоне от MIN_DOUBLE_VALUE до MAX_DOUBLE_VALUE, верно?; точно так же любое значение с плавающей запятой от MIN_FLOAT_VALUE до MAX_FLOAT_VALUE. Я хочу сопоставить любое значение, определенное в большем диапазоне (двойное), со значением, определенным в меньшем диапазоне (с плавающей запятой). Большинство значений в большем диапазоне (double) в конечном итоге будут сопоставлены с тем же значением в меньшем диапазоне (с плавающей запятой); но он все равно сохранит относительное расстояние до максимальных и минимальных значений. Допустим, у меня есть значение, определенное в диапазоне 0-9, и я хочу сопоставить его с диапазоном 0-1; в свою очередь, все значения меньше 4 будут отображаться в 0, тогда как остальные будут в 1.   -  person iliTheFallen    schedule 15.03.2013
comment
Майкл, кстати, мне очень жаль, что я не видел твоего сообщения; но ваше решение кажется выполнимым на самом деле! Я попробую! Благодарю вас! С другой стороны; вы знаете, я просто хотел знать, есть ли способ добиться этого с помощью побитовых операций; но вы же знаете, что ускорение есть ускорение :)   -  person iliTheFallen    schedule 15.03.2013


Ответы (2)


Я не уверен, чего вы пытаетесь достичь, поскольку некоторые двойные значения находятся далеко за пределами диапазона float.

Но если вы готовы рискнуть потерять значения, которые слишком велики для float, попробуйте следующее:

float f = new Double(val).floatValue();

Изменить: это точно так же, как приведение к плавающему. :)

person Vegard    schedule 15.03.2013
comment
Как вы думаете, это достаточно быстро? вместо умножения и деления на АЛУ; он использует какое-то элегантное решение, такое как игра с битами двойного значения, чтобы преобразовать его в значение с плавающей запятой? - person iliTheFallen; 15.03.2013
comment
На самом деле, я проверил исходный код Java, и это то же самое, что приведение к типу float. - person Vegard; 15.03.2013
comment
Owww :( Тогда никакого сопоставления... В любом случае, большое спасибо, что обратили внимание на мой вопрос. Кажется, мне следует поиграться с представлениями значений double и float IEEE-754, чтобы найти способ сопоставить двойное значение с диапазоном [MIN_FLOAT_VALUE , MAX_FLOAT_VALUE] быстро и эффективно... - person iliTheFallen; 15.03.2013
comment
Как я уже сказал, я действительно не понимаю, чего вы пытаетесь достичь. Вставляя 64-битное значение в 32-битное, вы во многих случаях столкнетесь либо с потерей точности, либо просто со значением, которое слишком велико для переменной с плавающей запятой. Как заявил Мхуарес, кастинг, вероятно, настолько близок, насколько это возможно. - person Vegard; 15.03.2013

Это отображает значение двойной точности в число с плавающей запятой, которое имеет те же самые старшие 32 бита:

float mappedVal = Float.intBitsToFloat((int)(Double.doubleToLongBits(val)>>32));

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

person Joni    schedule 15.03.2013
comment
Что ж, очень фантастично :) .. Если это действительно сопоставляет двойное значение с диапазоном типа float; это действительно здорово, и то, что я ищу. Очень даже спасибо. Я попробую и дам вам знать, какой результат я действительно получаю. - person iliTheFallen; 17.03.2013
comment
Когда я сравниваю результат с тем, который я получаю из самого первого уравнения, которое я написал в своем посте; кажется, что они не равны друг другу. С другой стороны, он вычисляет некоторые разумные значения. Ну и какая логика в твоих словах? - person iliTheFallen; 18.03.2013
comment
Что ж. я использую формулу: float mappedValue = (float) (doubleValue * MAX_FLOAT_VALUE + 1) / MAX_DOUBLE_VALUE; и результат совсем другой, чем у вас по величине. - person iliTheFallen; 19.03.2013
comment
Это отображение основано на двоичном представлении чисел с плавающей запятой: оно сохраняет старшие биты и отбрасывает наименее значащие. Поскольку количество битов экспоненты различается между float и double, вы увидите большую разницу в величине. - person Joni; 19.03.2013
comment
Аааа, я думаю, я понимаю, что вы имеете в виду. дайте мне время, чтобы провести несколько экспериментов; тогда я смогу рассказать вам больше о влиянии вашего решения на мою проблему. Кроме того, спасибо за интерес к моей проблеме Джони. - person iliTheFallen; 20.03.2013