1

I have this assignment and while i don't get any error not even warning from the compiler.

uint16_t Buffer[40000];

for (int n=0; n<40000 ; n++){
Buffer[n] = (0.99 * cos(((2.0*PI)/40000)*n);
}

The Buffer is an unsigned short but as you can see inside there are float values inside.

The program does not work as expected.

Also i have another case where i am not sure if i need casting as this time, the final value is a float value.

int intVal;
float floatVal;

floatVal = intVal - intVal*Buffer[intVal];

Is this valid? Does it need casting? Or there is not reason to declare floatVal as float?

  • what exactly do you expect from the program to do? – foivaras Aug 1 '17 at 8:58
  • it is a real time audio manipulation application – user1584421 Aug 1 '17 at 9:01
  • this is irrelevant. What do you expect after executing your first snippet, to be the contents of Buffer? – foivaras Aug 1 '17 at 9:04
  • The first one has wrong parenthesis, and casting is correct, however everything between 0 and 0.9999999999 results into a 0 in uint16_t variable. – KIIV Aug 1 '17 at 9:04
  • 1
    What board are you trying to run that on? – Majenko Aug 1 '17 at 9:36
1

First part:

uint16_t Buffer[40000];

for (int n=0; n<40000 ; n++){
  Buffer[n] = (0.99 * cos(((2.0*PI)/40000)*n);
}

Buffer[n] will be filled with an uint16_t and implicit casting to an uint16_t will be used. I suggest you do such implicit castings explicitly (so add (uint16_t) ... if you want).

However, if you do not want this, either define the Buffer as float, or at least add + 0.5 to give better roundings (if that is improving, depends on your situation, but mathematically it is better).

thus:

static const uint8_t BUFFER_SIZE = 40000;
uint16_t Buffer[BUFFER_SIZE];

for (int n=0; n<BUFFER_SIZE; n++)
{
  Buffer[n] = (int) (0.99 * cos(((2.0*PI)/BUFFER_SIZE)*n));
}

The next one:

int intVal;
float floatVal;

floatVal = intVal - intVal*Buffer[intVal];

This is also 'compiler-correct', and an int value can be more easier converted to a float. You will not lose digits. However, to make it clear an explicit cast with (int) ... is better.

Thus:

int intVal;
float floatVal = (float) (intVal - intVal*Buffer[intVal]);
1

c will perform implied casts for standard data types, normally without issuing any warnings.

This can catch you out at times.

So if you try to store a float into an int then it will be rounded down to the next integer. Since floats sometimes have rounding errors this can result in the value being 1 less than expected. e.g. 5 / 2.5 should give 2.0 but due to rounding may result in 1.99999999999. When saved as an int that would then give a value of 1.

If you want to round to the nearest integer then first add 0.5.

While the casts are implied and so not technically needed it can sometimes be a good idea to still include them explicitly just to make it clearer in the code that values are going to get rounded down.

The other thing to keep in mind is how variable types are promoted by the implied casts.

e.g. consider the following two lines:

float x = 3 + 2/4.0;
float x = 3.0 + 2/4;

In the first the calculation it is: int + int / double = int + double = double
In the second it is: double + int / int = double + int = double

So both result in a double that is then converted to a float (arduino is a little non-standard here, doubles are just floats anyway).

However the resulting values will be different. The first one will give the expected 3.5 while the second one will give 3.0 because 2/4 is an integer calculation and will have a value of 0. In order to get the correct value either the 2 or the 4 must be cast to a float or double before the division operation takes place.

For your specific questions:
Buffer[n] = (0.99 * cos(((2.0*PI)/40000)*n); is perfectly valid, all calculations will be performed as doubles and the end result cast to an int however you may get rounding issues as mentioned above. Changing the line to Buffer[n] = (0.99 * cos(((2.0*PI)/40000)*n) + 0.5); will round to the nearest integer which is probably what you want.
For the second question, floatVal = intVal - intVal*Buffer[intVal]; there is no need for a cast, the value will be calculated as an int and then there is an implied cast to a float. However I'm not sure what the point of using a float is here since the result is always going to be an integer, using a float will only slow things down.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.