Представлять десятичные числа, используя целые числа - PullRequest
5 голосов
/ 21 марта 2019

Я пытаюсь найти способ решить мои аппаратные ограничения с помощью программного обеспечения.У меня проблема в том, что я могу писать только целые числа (целые числа) на моем оборудовании, но я хочу роскошь использовать десятичные числа при вычислении результатов и т. Д.

Здесь на ум приходят шестнадцатеричные числа с коэффициентом преобразования... Я могу технически отправить шестнадцатеричное значение типа (00) 1105 , а затем просто интерпретировать это как сторону программного обеспечения 11.05 (E ^ -2).

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

Существуют ли более эффективные способы решения этой проблемы? (Двоичные значения не являются опцией, поскольку существует ограничение длины сообщений, которые могут быть отправлены. (длина <= 10) </strong>. Я не буду превышать E ^ 5 (nnnnn) дляпредполагаемое использование.)

У этого текущего подхода есть очевидные проблемы, и у всех подходов, вероятно, будет это , но Мне любопытно, как еще можно достичь этого?

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

Ответы [ 3 ]

2 голосов
/ 21 марта 2019

Из того, что я могу понять из вопроса, вам могут помочь фиксированные точки.Фиксированные точки позволяют выполнять десятичную арифметику с целыми числами, предполагая, что число цифр после десятичной точки известно заранее.

Вот быстрая и грязная реализация фиксированных точек:

#include <stdio.h>

#define FP_ABS(x) ((x) >= 0 ? (x) : -(x))

// This will determine the number of digits after the decimal point.
// It must be a power of 10.
// In this case, you can represent all the numbers in the range -2147483.648 to 2147483.647
// or if you want to be safe -2000000.000 to 2000000.000
#define FP_DECIMAL_FACTOR 1000

#define FP_LIT(x) ((int)((x) * FP_DECIMAL_FACTOR))
#define FP_ADD(x, y) ((x) + (y))
#define FP_SUB(x, y) ((x) - (y))
#define FP_MUL(x, y) ((x) * (y) / FP_DECIMAL_FACTOR)
#define FP_DIV(x, y) ((x) * FP_DECIMAL_FACTOR / (y))

#define FP_INT_PART(x) ((x) / FP_DECIMAL_FACTOR)
#define FP_DEC_PART(x) (FP_ABS((x) % FP_DECIMAL_FACTOR))


int main()
{
    int a = FP_LIT(25.01);
    int b = FP_LIT(12.2);

    printf("a = %d.%03d\n", FP_INT_PART(a), FP_DEC_PART(a));
    printf("b = %d.%03d\n", FP_INT_PART(b), FP_DEC_PART(b));

    int a_plus_b = FP_ADD(a, b);
    printf("a + b = %d.%03d\n", FP_INT_PART(a_plus_b), FP_DEC_PART(a_plus_b));

    int a_minus_b = FP_SUB(a, b);
    printf("a - b = %d.%03d\n", FP_INT_PART(a_minus_b), FP_DEC_PART(a_minus_b));

    int b_minus_a = FP_SUB(b, a);
    printf("b - a = %d.%03d\n", FP_INT_PART(b_minus_a), FP_DEC_PART(b_minus_a));

    int a_multiply_b = FP_MUL(a, b);
    printf("a * b = %d.%03d\n", FP_INT_PART(a_multiply_b), FP_DEC_PART(a_multiply_b));

    int a_divide_b = FP_DIV(a, b);
    printf("a / b = %d.%03d\n", FP_INT_PART(a_divide_b), FP_DEC_PART(a_divide_b));

    int b_divide_a = FP_DIV(b, a);
    printf("b / a = %d.%03d\n", FP_INT_PART(b_divide_a), FP_DEC_PART(b_divide_a));

    return 0;
}
1 голос
/ 21 марта 2019

вы не совсем ясны, если вам просто нужно выполнять вычисления с плавающей запятой без FPU, просто используйте библиотеки типа Библиотека с плавающей запятой для целочисленных процессоров

0 голосов
/ 21 марта 2019

Я помню, что сделал что-то подобное на экзамене.Я думаю, это зависит от приложения.

Для числовой обработки вы можете сделать что-то вроде этого:

  • масштабировать все числа в диапазоне [-1; 1], вычитая средние значенияи деление на максимум модулей.Таким образом, умножения будут принадлежать одному и тому же диапазону
  • Умножить все числа на степень 2 в зависимости от вашей архитектуры (например, 2^32 или 2^64)
  • Округлить значения доцелое число
  • Выполняйте свои операции
  • Масштабируйте значения путем деления на степень 2
  • Верните числа в исходный диапазон

Iсообщу вам подробности, как только смогу.

...