Преобразование плавающей точки к фиксированной точке

Хотя @fhdhsni дал вам отличный ответ, если вы беспокоитесь о читабельности, я бы предложил абстрагировать все это в отдельную функцию, например так:

defmodule T do 
    def parsefloats(stringtobeparsed) do
        stringtobeparsed
        |> String.replace("[", "")
        |> String.replace(",", "")
        |> String.replace("]", "")
        |> String.split(" ")
        |> Enum.map(fn x -> String.to_float(x) end)
    end
end   

Затем вы называете это так: [113 ]

[x,y] = T.parsefloats("[40.45694301152436, -3.6907402812214514]")
# [40.45694301152436, -3.6907402812214514]
iex(3)> x
# 40.45694301152436
iex(4)> y
# -3.6907402812214514

Не лучше с точки зрения более компактного кода, но, я думаю, более читабельного.

21
задан Kevin 9 October 2008 в 15:37
поделиться

6 ответов

Здесь Вы идете:

// A signed fixed-point 16:16 class
class FixedPoint_16_16
{
    short          intPart;
    unsigned short fracPart;

public:
    FixedPoint_16_16(double d)
    {
        *this = d; // calls operator=
    }

    FixedPoint_16_16& operator=(double d)
    {
        intPart = static_cast<short>(d);
        fracPart = static_cast<unsigned short>
                    (numeric_limits<unsigned short> + 1.0)*d);
        return *this;
    }

    // Other operators can be defined here
};

РЕДАКТИРОВАНИЕ: Вот более общий класс на основе anothercommon способа иметь дело с числами фиксированной точки (и на который KPexEA указал):

template <class BaseType, size_t FracDigits>
class fixed_point
{
    const static BaseType factor = 1 << FracDigits;

    BaseType data;

public:
    fixed_point(double d)
    {
        *this = d; // calls operator=
    }

    fixed_point& operator=(double d)
    {
        data = static_cast<BaseType>(d*factor);
        return *this;
    }

    BaseType raw_data() const
    {
        return data;
    }

    // Other operators can be defined here
};


fixed_point<int, 8> fp1;           // Will be signed 24:8 (if int is 32-bits)
fixed_point<unsigned int, 16> fp1; // Will be unsigned 16:16 (if int is 32-bits)
28
ответ дан 29 November 2019 в 06:54
поделиться

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

, Если Вы хотите 16:16

double f = 1.2345;
int n;

n=(int)(f*65536);

, если Вы хотите 24:8

double f = 1.2345;
int n;

n=(int)(f*256);
21
ответ дан 29 November 2019 в 06:54
поделиться

Редактирование **** **: Мой первый комментарий относится перед редактированием Kevin, но я оставлю его здесь для потомства. Ответы изменяются так быстро здесь иногда!

проблема с подходом Kevin состоит в том, что с Фиксированной точкой Вы обычно упаковываете в гарантируемый размер слова (обычно 32 бита). Объявление этих двух частей отдельно оставляет Вас прихоти упаковки структуры Вашего компилятора. Да Вы могли вызвать его, но это ни на что не работает кроме 16:16 представления.

KPexEA ближе к метке путем упаковки всего в интервал - хотя я использовал бы "подписываемый долго" для попытки быть явным на 32 битах. Тогда можно использовать его подход для генерации значения фиксированной точки, и разрядное разрезание действительно извлекает составные части снова. Его предложение также покрывает 24:8 случай.

(И все остальные, кто предложил просто static_cast....., что Вы думали?;))

7
ответ дан 29 November 2019 в 06:54
поделиться

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

Это использовало шаблоны и было легко угробить зависимости от lib повышения.

1
ответ дан 29 November 2019 в 06:54
поделиться

Это хорошо для преобразования от плавающей точки до целого числа, но O.P. также хотел фиксированная точка .

Теперь, как Вы сделали бы это в C++, я не знаю (C++, не являющийся чем-то, в чем я могу думать с готовностью). Возможно, попробуйте масштабировано-целочисленный подход, т.е. используйте целое число на 32 или 64 бита и программно выделите последнее, скажем, 6 цифр к тому, что имеет на правой стороне десятичную точку.

0
ответ дан 29 November 2019 в 06:54
поделиться

Нет никого созданного в поддержке в C++ для чисел фиксированной точки. Ваш лучший выбор состоял бы в том, чтобы записать обертке класс 'FixedInt', который берет, удваивает и преобразовывает их.

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

for (int i = 1; i <= precision; i++)
{
   if (decimal_part > 1.f/(float)(i + 1)
   {
      decimal_part -= 1.f/(float)(i + 1);
      fixint_value |= (1 << precision - i);
   }
}

, хотя это, вероятно, будет содержать ошибки все еще

-4
ответ дан 29 November 2019 в 06:54
поделиться
Другие вопросы по тегам:

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