2014-02-08 2 views
0

Я работаю в embedded c, переменная x - это данные датчиков, которые являются целыми числами (лежит между 1 и 100), и мне нужно вывести переменную y на lcd как линейное отношение x, но после округления ее до ближайшего целого числа, будет ли этот код работать? Если нет, то каковы другие способы сделать то же самое.Как получить самые близкие значения целого во встроенных c?

int x 
float y 
int z 
x=4 /*say its 4*/ 
y=((x*3.45)+3.5) /*which is a decimal*/ 
z=(unsigned int)(y) 
+0

Вы хотите реализовать круглые(), напольные() и потолочные()? Например, floor() получает целочисленную часть и вычитает из действительного значения и имеет значение, проверьте, меньше ли это 0,5, а затем дайте слово, иначе дайте слово + 1. Негативы включены? floor() требует bittwiddling. –

+0

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

ответ

1
int z = ((x * 3.45) + 3.5) + 0.5; /* assuming x is non-negative */ 

с плавающей точкой в ​​целом покрываются неявным преобразованием, так что вам не нужно делать это явно. Но преобразование - это усечение, поэтому дополнительный +0.5 доставит вам фактическое ближайшее целое число.

+0

Что? Я думаю, вы должны добавить предупреждения компилятора - я бы никогда не использовал неявное целочисленное действие, это может вызвать самые странные проблемы. –

+2

Если быть точным, '+ 0,5' округляется до ближайшего, наполовину от 0 (в случае, если х положителен). – mb84

+0

Не будет предупреждений о компиляторе, поскольку это стандартное неявное преобразование. Хорошо определено, что '' Когда конечное значение реального плавающего типа преобразуется в целочисленный тип, отличный от _Bool, дробная часть отбрасывается (т. Е. Значение усекается к нулю). «Оно не определено» Если значение неотъемлемой части не может быть представлено целым типом «', но это не является проблемой на фоне этого вопроса. – neverhoodboy

1

Альтернативное предложение:

Если ваш код работает на фиксированной точке процессор, то любая операция с плавающей точкой заменяется компилятором с вызовом библиотечной функции (как правило, предоставленной производителем , как часть BSP).

В таком случае вы можете избежать вызова операций с плавающей запятой в своем коде.

Создать хэш-таблицу для всех значений в указанном диапазоне (0-100):

int hash[101] = 
{ 
     4, 7, 10, 14, 17, 21, 24, 28, 31, 35, 38, 41, 45, 48, 52, 55, 59, 62, 66, 69, 
    73, 76, 79, 83, 86, 90, 93, 97,100,104,107,110,114,117,121,124,128,131,135,138, 
    142,145,148,152,155,159,162,166,169,173,176,179,183,186,190,193,197,200,204,207, 
    211,214,217,221,224,228,231,235,238,242,245,248,252,255,259,262,266,269,273,276, 
    280,283,286,290,293,297,300,304,307,311,314,317,321,324,328,331,335,338,342,345, 
    349 
}; 

Затем, простое использование y = hash[x] для каждого заданного значения x.

+0

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

+0

Да; Это действительно вопрос времени и пространства. Если вы можете освободить пространство памяти, необходимое для хэш-таблицы, вы можете быстрее запустить свой код. –

0

После комментария от @Joe Hass с ответом «после принятия».

Пропустить все математика с плавающей запятой.
Масштабируйте операцию и округлите, добавив 0.5 через 50u/100u.

int x;  // (lies between 1 and 100) 
unsigned z; 
#define A 345u /* 3.45 * 100 */ 
#define B 350u /* 3.5 * 100 */ 
// Do everything unsigned 
z = ((unsigned) x * A + B + 50u)/100u 

Это делает «округление до ближайшего, половину от 0» (@ mb84)
Примечание: Меньший масштаб 20 можно было бы использовать, но 100 понятнее.

Смежные вопросы