Итак, у вас есть значение байта (от 0 до 255), и вы хотите получить базу 45 журналов и сохранить ее в другом байте? Как уже говорили другие, вы потеряете некоторую точность в этом. Тем не менее, вы можете добиться большего успеха, чем просто приведение результата double
к byte
.
База 45 из 255 составляет приблизительно 1,455675. Вы можете сохранить это в байте с некоторой потерей точности, умножив его на постоянный коэффициент. Какой постоянный фактор? Вы можете использовать 100, что даст вам значение 145, но вы теряете почти половину диапазона байта. Поскольку наибольшее значение, которое вы хотите представить, равно 1.455675, вы можете использовать постоянный множитель 255/log45(255)
или около 175,176.
Насколько хорошо это работает? Посмотрим ...
var mult = 255.0 / Math.Log(255, 45);
Console.WriteLine("Scaling factor is {0}", mult);
double errMax = double.MinValue;
double errMin = double.MaxValue;
double errTot = 0;
for (int i = 1; i < 256; ++i)
{
// Get the log of the number you want
var l = Math.Log(i, 45);
// Convert to byte
var b = (byte)(l * mult);
// Now go back the other way.
var a = Math.Pow(45, (double)b / mult);
var err = (double)(i - a) / i;
errTot += err;
errMax = Math.Max(errMax, err);
errMin = Math.Min(errMin, err);
Console.WriteLine("{0,3:N0}, {1,3:N0}, {2}, {3:P4}", i, b, a, err);
}
Console.WriteLine("max error = {0:P4}", errMax);
Console.WriteLine("min error = {0:P4}", errMin);
Console.WriteLine("avg error = {0:P4}", errTot / 255);
В .NET 4 на моей машине это дает мне максимальную ошибку 2,1419% и среднюю ошибку 1,0501%.
Вы можете уменьшить среднюю ошибку, округлив результат с Math.Pow
. То есть:
var a = Math.Round(Math.Pow(45, (double)b / mult));
Это уменьшает среднюю ошибку до 0,9300%, но увеличивает максимальную ошибку до 3,8462%.