INFORMATION
My c++ program has no whole program optimization, has a Multi-Byte Character Set, and has enabled C++ Exceptions with SEH Exceptions (/EHa).
The following code reads information and then uses the read information in a simple math equation to determine the outcome.
PROBLEM
Here is an example to the situation that occurs!
For argument sake, underneath will show predetermined integer values, then the logic when the code is executed with these values.
healthalert = 19;
healthpercentage = 0; // THE PROBLEM IS HERE
health = 840;
fixedhealth = 840; // THIS SHOULD BE 885 AND NOT 840; IT IS 840 DUE TO HEALTHPERCENTAGE BEING 0 WHEN IT SHOULDN'T BE!
So in the first line of code determining the value of healthalert, the value is set to 19.
HOWEVER, when the equation for healthpercentage is calculated, even though healthalert is set to 19, the outcome for healthpercentage is zero?!?!?!?!!? WHY is this?
The next line is then executed and the value of health is 840.
Lastly, the value of fixedhealth is also 840; however, this should not be the case as it should be around 885. The reason fixedhealth is 840 is due to the math equation for healthpercentage outcoming to 0 when it shouldn't be!
Please help!
You mention SEH exceptions, but it looks like a simple case of integer division to me. You say healthalert is 19. Therefore 20 - healthalert is 1. Therefore, (20 - healthAlert)/20 is zero, because all the numbers involved are integers. Change that 20 to a 20.0, then cast back to an int at the end, and you should be fine.
Edit: Or do what Dark Falcon suggested seconds before I hit submit. :)
You don't give the variable types, but I'll bet they are integers. In that case, you're doing integer division, which truncates any fractional portion.
healthpercentage = (20 - healthalert) / healthalert * 100;
healthpercentage = (20 - 19) / 19 * 100;
healthpercentage = (int)(1 / 19) * 100;
healthpercentage = 0 * 100;
healthpercentage = 0;
If you want to continue to use integers, reorder operations so the multiplication is first:
healthpercentage = (20 - healthalert) * 100 / healthalert;
healthpercentage = (20 - 19) * 100 / 19;
healthpercentage = 1 * 100 / 19;
healthpercentage = (int)(100 / 19);
healthpercentage = 5;
Of course, even with this, the numbers don't match what you specified, so I don't understand your math. Perhaps this will still set you on the right track, however.
Related
I was going through the examples in K&R, and stumbled upon this bit of code:
celcius=5 * (fahr-32) / 9;
The author says that we can't use 5/9 since integer division truncation will lead to a value of 0.
The program however, outputs 17 as answer when fahr=0. By my calculations, (0-32)/9 should lead to -3 (due to truncation) and then -3*5 = -15, and NOT -17. Why does this happen?
(0 - 32) is first multiplied by 5, giving -160. -160 / 9 = -17.
What the author say is that one should not use
celsius = (fahr-32)*(5/9);
As for your question,
celsius = 5 * (fahr-32) / 9;
is different from
celsius = 5 * ((fahr-32) / 9);
In the later case, you would indeed get -15 when fahr=0.
I have this equation in solving the temperature from a temperature sensor.
variables are:
unsigned char AD_DATA; values is usually 100- 110;
int TEMP;
the original equation:
TEMP = 50 - (AD_DATA * 175) / 1000;
I changed that to:
TEMP = 500 - (AD_DATA * 1750) / 1000;
the reason for this is because TEMP is an integer, and thus on the first equation when it is calculated that there is a decimal it will be automatically rounded, so i changed it so that decimal will be included in the number.
The reason why I am not using float is because in the MCU I am using, whenever I declare a float variable inside the ISR(interrupt service routine) it will return an error thus I needed to be creative in using only INT, double will also return an error.
Now using an AD_DATA value of 100
the 1st equation will result to: 32.5, but since its an int it is now 33.
the 2nd equation should output 325, but in my output is 521
I need to include the decimal in my display thus it is really important for it to be included in the equation.
My ISR routine:
__interrupt void ADC_int(void){
IO_ADCSH.bit.INT = 0;
AD_DATA = IO_ADCRLH.DATA8;
TEMP = 500 - (AD_DATA * 1750) / 1000;
}
MCU specs
int 2bytes
long 4bytes
unsigned char 1byte
As a quick hack, you can replace (AD_DATA * 1750) / 1000 by (AD_DATA * 7) / 4.
For more ideas, read below.
Note that by changing
TEMP = 50 - (AD_DATA * 175) / 1000;
to
TEMP = 500 - (AD_DATA * 1750) / 1000;
you changed the meaning of the TEMP variable. Assuming it means "temperature" (doesn't really matter), it meant "temperature in degrees", and now it means "temperature in units of 1/10 degree". However, why did you multiply by 10? Just for convenience, I guess - you are not obliged to use powers of 10 for your units. You can use any other number, provided you remember what it was, and treat the result TEMP accordingly (e.g. divide it by 10 when printing it out). So the best number to use is 40: it eliminates a division (or rather, postpones it to later lines of code) and so avoids a loss of precision.
TEMP_MULTIPLIED_BY_40 = 2000 - AD_DATA * 7;
My first guess according to the information you gave,
is that the register length is 16bits causing the operand to overflow when you multiply AD_DATA by 1000.
the largest value a int could hold is 32762 (from the top of my head , more like 0x7FFF), even unsigned it is insufficient to hold AD_DATA*1000 ( wich in you case would be 18*1000=18000 ), the value will be truncated to 16bits, giving a negative number in the process.
you can fix that by specifying the length of your operator in your expression and casting AD_DATA to a 32bit word.
Is there a way to remove the following if-statement to check if the value is below 0?
int a = 100;
int b = 200;
int c = a - b;
if (c < 0)
{
c += 3600;
}
The value of c should lie between 0 and 3600. Both a and b are signed. The value of a also should lie between 0 and 3600. (yes, it is a counting value in 0.1 degrees). The value gets reset by an interrupt to 3600, but if that interrupt comes too late it underflows, which is not of a problem, but the software should still be able to handle it. Which it does.
We do this if (c < 0) check at quite some places where we are calculating positions. (Calculating a new position etc.)
I was used to pythons modulo operator to use the signedness of the divisor where our compiler (C89) is using the dividend signedness.
Is there some way to do this calculation differently?
example results:
a - b = c
100 - 200 = 3500
200 - 100 = 100
Good question! How about this?
c += 3600 * (c < 0);
This is one way we preserve branch predictor slots.
What about this (assuming 32-bit ints):
c += 3600 & (c >> 31);
c >> 31 sets all bits to the original MSB, which is 1 for negative numbers and and 0 for others in 2-complement.
Negative number shift right is formally implementation-defined according to C standard documents, however it's almost always implemented with MSB copying (common processors can do it in a single instruction).
This will surely result in no branches, unlike (c < 0) which might be implemented with branch in some cases.
Why are you worried about the branch? [Reason explained in comments to the question.]
The alternative is something like:
((a - b) + 3600) % 3600
This assumes a and b are in the range 0..3600 already; if they're not under control, the more general solution is the one Drew McGowen suggests:
((a - b) % 3600 + 3600) % 3600
The branch miss has to be very expensive to make that much calculation worthwhile.
#skjaidev showed how to do it without branching. Here's how to automatically avoid multiplication as well when ints are twos-complement:
#if ((3600 & -0) == 0) && ((3600 & -1) == 3600)
c += 3600 & -(c < 0);
#else
c += 3600 * (c < 0);
#endif
What you want to do is modular arithmetic. Your 2's complement machine already does this with integer math. So, by mapping your values into 2's complement arithmetic, you can get the modolo operation free.
The trick is represent your angle as a fraction of 360 degrees between 0 and 1-epsilon. Of course, then your constant angles would have to represented similarly, but that shouldn't be hard; its just a bit of math we can hide in a conversion function (er, macro).
The value in this idea is that if you add or subtract angles, you'll get a value whose fraction part you want, and whose integer part you want to throw away. If we represent the fraction as a 32 bit fixed point number with the binary point at 2^32 (e.g., to the left of what is normally considered to be a sign bit), any overflows of the fraction simply fall off the top of the 32 bit value for free. So, you do all integer math, and "overflow" removal happens for free.
So I'd rewrite your code (preserving the idea of degrees times 10):
typedef unsigned int32 angle; // angle*3600/(2^32) represents degrees
#define angle_scale_factor 1193046.47111111 // = 2^32/3600
#define make_angle(degrees) (unsigned int32)((degrees%3600)*angle_scale_factor )
#define make_degrees(angle) (angle/(angle_scale_factor*10)) // produces float number
...
angle a = make_angle(100); // compiler presumably does compile-time math to compute 119304647
angle b = make_angle(200); // = 238609294
angle c = a - b; // compiler should generate integer subtract, which computes 4175662649
#if 0 // no need for this at all; other solutions execute real code to do something here
if (c < 0) // this can't happen
{ c += 3600; } // this is the wrong representation for our variant
#endif
// speed doesn't matter here, we're doing output:
printf("final angle %f4.2 = \n", make_degrees(c)); // should print 350.00
I have not compiled and run this code.
Changes to make this degrees times 100 or times 1 are pretty easy; modify the angle_scale_factor. If you have a 16 bit machine, switching to 16 bits is similarly easy; if you have 32 bits, and you still want to only do 16 bit math, you will need to mask the value to be printed to 16 bits.
This solution has one other nice property: you've documented which variables are angles (and have funny representations). OP's original code just called them ints, but that's not what they represent; a future maintainer will get suprised by the original code, especially if he finds the subtraction isolated from the variables.
Consider an algorithm to test the probability that a certain number is picked from a set of N unique numbers after a specific number of tries (for example, with N=2, what's the probability in Roulette (without 0) that it takes X tries for Black to win?).
The correct distribution for this is pow(1-1/N,X-1)*(1/N).
However, when I test this using the following code, there is always a deep ditch at X=31, independently from N, and independently from the seed.
Is this an intrinsic flaw that cannot be prevented due to the implementation specifics of the PRNG in use, is this a real bug, or am I overlooking something obvious?
// C
#include <sys/times.h>
#include <math.h>
#include <stdio.h>
int array[101];
void main(){
int nsamples=10000000;
double breakVal,diffVal;
int i,cnt;
// seed, but doesn't change anything
struct tms time;
srandom(times(&time));
// sample
for(i=0;i<nsamples;i++){
cnt=1;
do{
if((random()%36)==0) // break if 0 is chosen
break;
cnt++;
}while(cnt<100);
array[cnt]++;
}
// show distribution
for(i=1;i<100;i++){
breakVal=array[i]/(double)nsamples; // normalize
diffVal=breakVal-pow(1-1/36.,i-1)*1/36.; // difference to expected value
printf("%d %.12g %.12g\n",i,breakVal,diffVal);
}
}
Tested on an up-to-date Xubuntu 12.10 with libc6 package 2.15-0ubuntu20 and Intel Core i5-2500 SandyBridge, but I discovered this already a few years ago on an older Ubuntu machine.
I also tested this on Windows 7 using Unity3D/Mono (not sure which Mono version, though), and here the ditch happens at X=55 when using System.Random, while Unity's builtin Unity.Random has no visible ditch (at least not for X<100).
The distribution:
The differences:
This is due to glibc's random() function not being random enough. According to this page, for the random numbers returned by random(), we have:
oi = (oi-3 + oi-31) % 2^31
or:
oi = (oi-3 + oi-31 + 1) % 2^31.
Now take xi = oi % 36, and suppose the first equation above is the one used (this happens with a 50% chance for each number). Now if xi-31=0 and xi-3!=0, then the chance that xi=0 is less than 1/36. This is because 50% of the time oi-31 + oi-3 will be less than 2^31, and when that happens,
xi = oi % 36 = (oi-3 + oi-31) % 36 = oi-3 % 36 = xi-3,
which is nonzero. This causes the ditch you see 31 samples after a 0 sample.
What's being measured in this experiment is the interval between successful trials of a Bernoulli experiment, where success is defined as random() mod k == 0 for some k (36 in the OP). Unfortunately, it is marred by the fact that the implementation of random() means that the Bernoulli trials are not statistically independent.
We'll write rndi for the ith output of `random()' and we note that:
rndi = rndi-31 + rndi-3 with probability 0.75
rndi = rndi-31 + rndi-3 + 1 with probability 0.25
(See below for a proof outline.)
Let's suppose rndi-31 mod k == 0 and we're currently looking at rndi. Then it must be the case that rndi-3 mod k ≠ 0, because otherwise we would have counted the cycle as being length k-3.
But (most of the time) (mod k): rndi = rndi-31 + rndi-3 = rndi-3 ≠ 0.
So the current trial is not statistically independent of the previous trials, and the 31st trial after a success is much less likely to succeed than it would in an unbiased series of Bernoulli trials.
The usual advice in using linear-congruential generators, which doesn't actually apply to the random() algorithm, is to use the high-order bits instead of the low-order bits, because high-order bits are "more random" (that is, less correlated with successive values). But that won't work in this case either, because the above identities hold equally well for the function high log k bits as for the function mod k == low log k bits.
In fact, we might expect a linear-congruential generator to work better, particularly if we use the high-order bits of the output, because although the LCG is not particularly good at Monte Carlo simulations, it does not suffer from the linear feedback of random().
random algorithm, for the default case:
Let state be a vector of unsigned longs. Initialize state0...state30 using a seed, some fixed values, and a mixing algorithm. For simplicity, we can consider the state vector to be infinite, although only the last 31 values are used so it's actually implemented as a ring buffer.
To generate rndi: (Note: ⊕ is addition mod 232.)
statei = statei-31 ⊕ statei-3
rndi = (statei - (statei mod 2)) / 2
Now, note that:
(i + j) mod 2 = i mod 2 + j mod 2 if i mod 2 == 0 or j mod 2 == 0
(i + j) mod 2 = i mod 2 + j mod 2 - 2 if i mod 2 == 1 and j mod 2 == 1
If i and j are uniformly distributed, the first case will occur 75% of the time, and the second case 25%.
So, by substitution in the generation formula:
rndi = (statei-31 ⊕ statei-3 - ((statei-31 + statei-3) mod 2)) / 2
= ((statei-31 - (statei-31 mod 2)) ⊕ (statei-3 - (statei-3 mod 2))) / 2 or
= ((statei-31 - (statei-31 mod 2)) ⊕ (statei-3 - (statei-3 mod 2)) + 2) / 2
The two cases can be further reduced to:
rndi = rndi-31 ⊕ rndi-3
rndi = rndi-31 ⊕ rndi-3 + 1
As above, the first case occurs 75% of the time, assuming that rndi-31 and rndi-3 are independently drawn from a uniform distribution (which they're not, but it's a reasonable first approximation).
As others pointed out, random() is not random enough.
Using the higher bits instead of the lower ones does not help in this case. According to the manual (man 3 rand), old implementations of rand() had a problem in the lower bits. That's why random() is recommended instead. Though, the current implementation of rand() uses the same generator as random().
I tried the recommended correct use of the old rand():
if ((int)(rand()/(RAND_MAX+1.0)*36)==0)
...and got the same deep ditch at X=31
Interstingly, if I mix rand()'s numbers with another sequence, I get rid of the ditch:
unsigned x=0;
//...
x = (179*x + 79) % 997;
if(((rand()+x)%36)==0)
I am using an old Linear Congruential Generator. I chose 79, 179 and 997 at random from a primes table. This should generate a repeating sequence of length 997.
That said, this trick probably introduced some non-randomness, some footprint... The resulting mixed sequence will surely fail other statistical tests. x never takes the same value in consecutive iterations. Indeed, it takes exactly 997 iterations to repeat every value.
''[..] random numbers should not be generated with a method chosen at random. Some theory should be used." (D.E.Knuth, "The Art of Computer Programming", vol.2)
For simulations, if you want to be sure, use the Mersenne Twister
I'm using two different variable to divide in the calculation with the variable from int and double. These work fine when I use something like:
int cost
cost = 40;
cost = (cost / 400) * 20 * 2;
For this the method works fine and I get the right result which is 4, but when I use the variable cost and put it in the header instead, like:
#define cost 40
int total_cost;
total_cost = (cost / 400) * 20 * 2;
this always results in 0 for me and I don't know why. Even if I use printf with %d or %f this still gives me a result of 0.
You are doing integer division - which rounds down.
Therefore:
cost / 400
is returning zero because cost = 40 and 40 / 400 rounds down to zero.
What you should do is use a floating-point type like double.
EDIT:
double cost
cost = 40;
cost = (cost / 400) * 20 * 2;
and
#define cost 40
double total_cost;
total_cost = ((double)cost / 400) * 20 * 2;
Order of operations, and Integer Division.
Integer Division always truncates. Mathematically, 40/400 = .1 - but that's not an integer. The remainder is thrown away, leaving you with: 40 / 400 = 0.
Order of operations means that the division is done first, in your example. Since the order of multiplication and division doesn't matter too much (mathematically speaking), try changing the order:
total_cost = cost * 20 * 2 / 400;
Multiplication happens first, division last, giving you:
40 * 20 * 2 / 400 = 800 * 2 / 400 = 1600 / 400 = 4