Home » Arduino » Supostos problemas de cálculo aritmético no Arduino

Supostos problemas de cálculo aritmético no Arduino

1. Multiplicação com erro

Muitos reclamações existem a respeito de um possível erro de compilação (ou bug na execução) no arduino no que se refere a sua ULA (Unidade Lógica e aritmética). Por exemplo, no código abaixo, alguns esperariam que fosse exibido na serial o texto :

Resultado = 134000

void setup()
{
 Serial.begin(115200);
}

void loop()
{
int sensor; //Dado de um sensor
long resultado;

 sensor = 134;

 resultado = sensor * 1000;

 Serial.print("Resultado = ");
 Serial.println(resultado);
}

Aparece, no entanto,  “Resultado = 2928

A variável sensor é do tipo int, que na arquitetura ATmega328p (arduino Uno e semelhantes) ocupa apenas 2 bytes (15 bits para o valor e um bit para o sinal), logo a faixa de representação de valores varia de -32.768 a 32.767, sendo incapaz de armazenar o valor 134.000 .

E por que aparece 2928 como resultado ? Veja o cálculo:

  0x86    (134 em decimal)
x 0x3E8   (1000)
---------
0x20B70   (134000)

No entanto como só tempos 2 bytes para representar o resultado, pois tanto a variável sensor quanto o valor 1000 são armazenados em varáveis temporárias do tipo int, então para cálculo intermediário também será usada uma variável do tipo int, ou seja, usados apenas 2 bytes.  Logo :

em 0x20B70    a parte mais significativa será desprezada ficando apenas  0x0B70 que em decimal vale 2928

Solução

1. Conhecer muito bem  os tipos primitivos  e suas faixas de representação de valores:

Tipos Tamanho em bytes Faixa de valores

int

2

–32768 a 32767

unsigned int

2

0 a 65535

long

4

–2147483648 a 2147483647

unsigned long

4

0 a 4294967295

float

4

3.4028235E+38 a –3.4028235E+38

double

4

 mesmo que float

boolean

1

false (0) ou true (1)

char

1

–128 a 127

byte

1

0 a 255

2. Com relação ao código acima, apenas insira um ‘L’ no final de uma constante inteira para esta passar a ser representada como um valor long, assim em cálculos intermediários serão salvos sempre em registros deste tipo.

  ...
  resultado = sensor * 1000L;
  ...
}

3. Observe que erros mais sutis podem ocorrer se tais conceitos não forem muito bem interiorizados, No exemplo abaixo, como somente a constante  1000L  aparece definida como long através do sufixo ‘L’,  os demais números que a antecede participarão do cálculo como inteiros.

const unsigned long  DIA_MILI  = (24 * 60 * 60 * 1000L);
}

Dessa forma a sub-expressão inicial “24 * 60 * 60” excederá a capacidade dos 31 bits para representá-lo gerando um valor truncado e definindo uma  constante errada.

Defina a primeira constante como long  ou todas para que o compilador faça o cast das demais de forma correta.

const unsigned long  DIA_MILI  = (24L * 60L * 60L * 1000L);
}

Referências

  1. arduino.cc
1235 Total 7 Visualizações

About 

System development consultant
He graduated from UFF in Software development
A lot of experience in development process and management .
International expertise : USA (1 yr) and Italy (3 yrs) where He played as system team leader .
Fluently in italian and english.
He Lives now in Rio de Janeiro, Brazil

    Find more about me on:
  • googleplus
, ,