Мы можем видеть насыщенные цвета (полный красный, зеленый и/или синий) в преобразованном изображении при достижении черного цвета в исходном изображении. Я думаю, что функция не работает очень хорошо рядом с 0.
Я сделал быструю реализацию wikipedia explanation of norm of the float 16 bits.
<html>
<head>
<script>
var _floatToHalfFloat = #### YOUR FUNCTION HERE CUT ####
var _halfFloatToFloat = function(hf) {
var m = new ArrayBuffer(2);
var n = new Uint16Array(m);
n[0] = hf;
var sign = n[0] & 0x8000;
var exp = (n[0] >> 10) & 0x1F;
var mant = n[0]& 0x03FF;
document.getElementById('sign').innerHTML += sign+" - ";
document.getElementById('exp').innerHTML += exp+" - ";
document.getElementById('mant').innerHTML += mant+" - ";
if (exp == 0x1F) {
return 1.0 * Math.pow(-1, sign) * Infinity;
} else if (exp == 0) {
return Math.pow(-1, sign) *
Math.pow(2, -14) *
(mant/Math.pow(2, 10));
} else {
return Math.pow(-1, sign) *
Math.pow(2, exp-15) *
(1+(mant/Math.pow(2, 10)));
}
};
document.addEventListener("DOMContentLoaded", function(event) {
var input = new Float32Array(8);
input[0] = 2.5;
input[1] = 0.25;
input[2] = 0.025;
input[3] = 0.025;
input[4] = 0.0025;
input[5] = 0.00025;
input[6] = 0.000025;
input[7] = 0.0;
var i, s = "Value before = ";
for (i = 0; i < input.length; i++)
s += input[i] + " - ";
document.getElementById('res1').innerHTML = s;
var output = _floatToHalfFloat(input, 0);
s = "Value after = ";
for (i = 0; i < output.length; i++)
s += _halfFloatToFloat(output[i]) + " - ";
document.getElementById('res2').innerHTML = s;
});
</script>
</head>
<body>
<span id="res1">result</span></br>
<span id="res2">result</span></br>
</br></br></br>
<span id="sign">signs =</span></br>
<span id="exp">exponents =</span></br>
<span id="mant">mantissas =</span></br>
</body>
</html>
Результаты испытаний приведены ниже:
Value before = 2.5 - 0.25 - 0.02500000037252903 - 0.02500000037252903 - 0.0024999999441206455 - 0.0002500000118743628 - 0.00002499999936844688 - 0 -
Value after = 2.5 - 0.25 - 0.024993896484375 - 0.024993896484375 - 0.002498626708984375 - 0.0002498626708984375 - Infinity - 2 -
signs =0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 -
exponents =16 - 13 - 9 - 9 - 6 - 3 - 31 - 16 -
mantissas =256 - 0 - 614 - 614 - 286 - 24 - 653 - 0 -
Это показывает, что 2 последняя информация не является когерентной. 0,000025 преобразуется в Бесконечность (а не 0?), А само само преобразуется в 2. Это не кажется правильным. Когда вы хотите закодировать нуль, «википедия говорит», ваша мантисса И ваш показатель должен быть равен нулю. В коде, который вы указали, мантисса равна нулю, а показатель составляет 16, что приводит к 2 (2^(16-15)).
После некоторой настройки вашей функции кажется, что все случаи рассматриваются как обычные. Это связано с ошибкой в ваших операторах if. Поэтому вместо того, чтобы:
} else if(n === 0) {
input[i] = 0;
}
Вы хотите, вероятно, сделать что-то вроде этого:
} else if(n[0] === 0) {
input[i] = 0;
}
И то же самое для всех видов использования n
переменной. Но у вас все еще есть проблема с переполнением. Возможно, вы можете найти приемлемый вариант:
} else if(Math.abs(n[0]) < 0.0001) {
input[i] = 0;
}