Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

424
Visualizações
C: Representing a fraction without floating points

I'm writing some code for an embedded system (MSP430) without hardware floating point support. Unfortunately, I will need to work with fractions in my code as I'm doing ranging, and a short-range sensor with a precision of 1m isn't a very good sensor.

I can do as much of the math as I need in ints, but by the end there are two values that I will definitely need to have fractions on; range and speed. Range will be a value between 2-500 (cm), while speed should be no higher than -10 to 10 (ms^-1). I am unsure how to represent them without floating point values, if it is possible. A simple way of rounding the fractions up or down would be best.

Some sample code I have:

voltage_difference_new = ((memval3_new - memval4_new)*3.3/4096); where memval3_new and memval4_new are ints, but voltage_difference_new is a float.

Please let me know if more information is needed. Or if there is a blindingly easy fix.

over 4 years ago · Santiago Trujillo
1 Respostas
Responde à pergunta

0

You have rather answered your own question with the statement:

Range will be a value between 2-500 (cm),

Work in centimetre (or even millimetre) rather than metre units.

That said you don't need floating-point hardware to do floating point math; the compiler will support "soft" floating point and generate the code to perform floating point operations - it will be slower than hardware floating point or integer operations, but that may not be an issue in your application.

Nonetheless there are many reasons to avoid floating-point even with hardware support and it does not sound like your case for FP is particularly compelling, but it is hard to tell without seeing your code and a specific example. In 32 years of embedded systems development I have seldom resorted to FP even for trig, log, sqrt and digital signal processing.

A general method is to use a fixed point presentation. My earlier suggestion of using centimetres is an example of decimal fixed point, but for greater efficiency you should use binary fixed point. For example you might represent distance in 1/1024 metre units (giving > 1 mm precision). Because the fixed point is binary, all the necessary rescaling can be done with shifts rather than more expensive multiply/divide operations.

For example, say you have an 8 bit sensor generating linear output 0 to 255 corresponding to a real distance 0 to 0.5 metre.

#define Q10_SHIFT = 10 ; // 10 bits fractional (1/1024)
typedef int q10_t ;

#define ONE_METRE = (1 << Q10_SHIFT)
#define SENSOR_MAX = 255
#define RANGE_MAX = (ONE_METRE/2)

q10_t distance = read_sensor() * RANGE_MAX / SENSOR_MAX ;

distance is in Q10 fixed point representation. Performing addition and subtraction on such is normal integer arithmentic, multiply and divide require scaling:

int q10_add( q10_t a, q10_t b )
{
    return a + b ;
}

int q10_sub( q10_t a, q10_t b )
{
    return a - b ;
}

int q10_mul( q10_t a, q10_t b )
{
    return (a * b) >> Q10_SHIFT ;
}

int q10_div( q10_t a, q10_t b )
{
    return (a << Q10_SHIFT) / b ;
}

Of course you may want to be able to mix types and say multiply a q10_t by an int - providing a comprehensive library for fixed-point can get complex. Personally for that I use C++ where you have classes, function overloading and operator overloading to support more natural code. But unless your code has a great deal of general fixed point math, it may be simpler to code specific fixed point operations ad-hoc.

To take the one example you have provided:

double voltage_difference_new = ((memval3_new - memval4_new)*3.3/4096);

The floating-point there is trivially removed using millivolts:

int voltage_difference_new_mv = ((memval3_new - memval4_new) * 3300) /4096 ;

The issue then perhaps becomes one of presentation. For example if you have to present or report the value in volts to a user. In that case:

int volt_fract = abs(voltage_difference_new_mv % 1000) ;
int volt_whole = voltage_difference_new_mv / 1000 ;
printf( "%d.%04d", volt_whole, volt_fract ) ;
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda