Как автоматически масштабировать значение с плавающей запятой в C? - PullRequest
0 голосов
/ 26 сентября 2018

Я работаю на встроенном устройстве, которое измеряет напряжение через 16-битный АЦП.С 3,3 В в качестве эталона у меня есть разрешение 50 мкВ.Таким образом, устройство может измерять напряжение от 50 мкВ до 3,3 В и, таким образом, основываясь на текущем значении, мне нужно отформатировать его и отобразить в мВ, или мкВ или В и т. Д.

Значение является плавающей точкой.

Существует ли библиотечный API, который это делает, или я должен написать свой собственный код?

1 Ответ

0 голосов
/ 26 сентября 2018

Как автоматически масштабировать значение с плавающей запятой в C?

Автоматическое масштабирование до степеней 1000 имеет тонкие соображения относительно переходов, которые даже закодировали его OP, вероятно, он потерпел бы неудачув угловых случаях.

Давайте попробуем немного другую, но более простую цель: напечатать до 3 значащих цифр со степенью 1000.0

// example output
1.00
9.99
10.0
99.9
100.
999.
1.00k
9.99k
10.0k
...

Код может попытаться сделать это ссвою собственную математику с использованием log() и т. д., но она всегда будет терпеть неудачу в случаях около 9,995, 99,95, 999,5.

Пусть sprintf() выполнит тяжелую работу, а затем будет использовать манипуляции со строками.


Первым шагом является печать в строку с использованием "%e"

//            sgn  dig  . digs  e  sgn expo \0 
#define FLT_E2 (1 + 1 + 1 + 2 + 1 + 1 + 5 + 1)
// let us double buffer size as there is little reason to be stingy here.
char buf[FLT_E2 * 2];  

//                           v--- 2 digits after the lead digit
snprintf(buf, sizeof buf, "%.2e", some_float);

Следующим шагом является обработка строки в 3 части и использование "%n", чтобы отметить смещение десятичной точкии 'e'.

int whole, frac, expo, dp, e;
if (sscanf(buf, "%d%n.%d%ne%d", &whole, &dp, &frac, &e, &expo) != 3) {
  // value is some non-finite like infinity or not-a-number.
  printf("%e", some_float);  
  return;
}

Теперь переместите expo на кратное 3 и сдвиньте десятичную точку.

while (expo%3) {
  expo--;
  buf[dp] = buf[dp+1];
  buf[++dp] = '.';
}

Преобразуйте 'e' в различные Префикс SI .

// TBD code to handle expo out of range [-24 24], left for OP.

char prefix = "yzafpnum kMGTPEZY"[(expo - -24)/3];
if (prefix != ' ') buf[e++] = prefix;
buf[e] = '\0';

Теперь выведите

printf("%s", buf);

Хотя здесь есть много деталей с этими непроверенными фрагментами кода, окончательный код оставлен для формирования OP.

Дополнительные проблемы включают в себя:
обработка специфических для локали десятичных точек, таких как ','
показатели снаружи [-24 ... 24].
μ против вас.

...