How can I get more accurate values dividing two long?

3
I'm programming a CNC on my own, and I'm in the middle of my code, and now I have two variables of type long that when split results in an exact fractional value but the Arduino returning a fractional value of only 2 houses.

long x = 99;
long y = 9;
long z = 9999;
long m = 9999;

(double)x/(double)m; //resulta em 0.01
(double)y/(double)m; //resulta em 0.00
(double)z/(double)m; //resulta em 1.00

How can I get more accurate values by dividing two values long ?

obs .: The maximum result of the division will be 1.00

    
asked by anonymous 01.07.2015 / 09:17

2 answers

2
(double)x/(double)m; //resulta em 0.01
(double)y/(double)m; //resulta em 0.00
(double)z/(double)m; //resulta em 1.00
99/9999 = 0.00990099(0099...)  
9/9999 = 0.00090009(0009...)

Possibly your problem is in printf() , not calculation:

printf(" com 2 dígitos de precisão: %.2f\n", 9.0/9999);
printf("                   default: %f\n", 9.0/9999); // 6 dígitos
printf("com 15 dígitos de precisão: %.15f\n", 9.0/9999);

that gives the result:

% ./a.out
 com 2 dígitos de precisão: 0.00
                   default: 0.000900
com 15 dígitos de precisão: 0.000900090009001
    
01.07.2015 / 09:36
1

See in principle your problem is when using the function print / println of the object Serial these functions when dealing with numbers of type float and double allows you to enter how many digits will be used for the fractional part of the number provided. The default is two so your problem comes down to this, using a larger number of houses as in the example below where I used 30 houses, which is well beyond the Arduino's capable resolution, whatever the architecture used.

But note, there is some knowledge you may already have, but it is important to strengthen .

In the Arduino MEGA is used 8-bit microcontrollers of the AVR family, so the numeric type you chose, long occupies four bytes but does not allow fractions or is floating point.

So you need to Casting for a higher precision type, Arduino MEGA or another 8-bit family, it will make no difference in using Float or Double , you will have the same precision that will be 6 to 7 digits, with the limit values being 3.4028235E + 38 and a minimum of -3.4028235E + 38.

But in the Arduino DUE family or ARM microcontrollers that are 32 bits, you will have a greater precision using the Double type since this will occupy 8 bytes (even the documentation saying that double and long are the same size), and these have 15-digit precision.

void setup() {
  Serial.begin(9600);

  long x = 234;
  long y = 343;
  long z = 731;

   Serial.println(x/y);
   Serial.println(x/(float)y,30);
   Serial.println(x/(double)y,30);

   Serial.println(x/z);
   Serial.println(x/(float)z,30);
   Serial.println(x/(double)z,30);

   Serial.println(y/z);
   Serial.println(y/(float)z,30);
   Serial.println(y/(double)z,30);

   Serial.println(z/y);
   Serial.println(z/(float)y,30);
   Serial.println(z/(double)y,30);

}

void loop() {
  // put your main code here, to run repeatedly:

}

In the code above, if run on the Arduino Mega (or another one from the AVR family - 8-bits ) will have the following result: / p>

58
58.500000000000000000000000000000  
58.500000000000000000000000000000

0
0.320109415054321289062500000000
0.320109415054321289062500000000

0
0.005471956253051757812500000000
0.005471956253051757812500000000

182
182.750000000000000000000000000000
182.750000000000000000000000000000

On the other hand, Arduino DUE (and others in the ARM family - 32-bit ) will give the following result: p>

58
58.500000000000000000000000000000
58.500000000000000000000000000000

0
0.320109426975250244140625000000
0.320109439124487016314901666191

0
0.005471956450492143630981445312
0.005471956224350204678330555907

182
182.750000000000000000000000000000
182.750000000000000000000000000000

ATTENTION

Notice the precision failure that occurs in Arduino DUE when using float, and asks Serial.println() to print to 30 decimal places.

Types Sizes

Long

32 bits (4 bytes), from -2,147,483,648 to 2,147,483,647

Double

3.4028235E + 38 maximum and minimum -3.4028235E + 38. In the Arduino MEGA and family occupy (4 bytes) of information.

Already in the Arduino DUE and family occupy (8 bytes) of information.

Float

Identical to Double in the Arduino Mega and family, but care 2.0 is different from (4 / 2.0), due to the numerical coding method adopted ( IEEE 754 for 32-bit floating point numbers).

In Arduino DUE presents unexpected results when using greater precision.

int (Integer)

From -32,768 to 32,767 for the Arduino Mega and family, since it occupies 2 bytes

In Arduino Due, use 32-bit (4-byte). being therefore from -2,147,483,648 to 2,147,483,647 or identical to long

More information:

  • link
  • link
  • link
  • link
  • link
  • link
  • link
  • 06.07.2015 / 23:37