I'm writing my own method to generate a random number with C as follows:
int randomNumber(){
int catch = *pCOUNTER;
int temp = catch;
temp /= 10;
temp *= 10;
return (catch - temp);
}
pCounter is basically a pointer to a register in the device I'm using. The number in that register is always increasing so my idea is to take the first digit only.
At some point, the number returned becomes larger than 9 and I'm not sure if the problem is in my code or the device itself. The device is an Altera DE1 board.
Can anyone please help with that?
Thanks!
Did you declare pCounter as volatile?
volatile unsigned *pCounter = (unsigned *)0xBADDECAF;
int randomNumber(){
return *pCounter % 10;
}
To achieve what you're trying to do in your code:
int catch = *pCOUNTER;
return (catch % 10); // Returns only the ones digit
However, I question if this approach is anywhere close to being reasonably random...
Are you sure you're not looking to use %= instead of /= & *=?
I suspect that your problem might be an 'optimization' introduced by the compiler - if you don't have pCOUNTER declared with the correct volatility, the compiler could be reading through the pointer more than once. I have no idea how many registers your processor might have - if there's not enough to hold catch in a register, it might read it multiple times (once to get something to do the temp calculations on, and again for the final return value).
Try the following, which should ensure that the pCOUNTER device/register is read exactly once:
int randomNumber(){
int catch = *(int volatile*)pCOUNTER;
int temp = catch;
temp /= 10;
temp *= 10;
return (catch - temp);
}
If you're looking for a random digit (0-9 only), try this modification of your method.
int randomNumber(){
return ((*pCOUNTER) % 10);
}
This isn't very random, though. If it's always increasing, presumably at a known rate then it's 100% predictable, not random at all.
Is the rand() function not allowed on that Altera board?
Edit:
You could always write your own PRNG. I did a Google search for "simple random number generator code", and found several simple examples. The simplest ones are along these lines:
int randomNumber()
{
static long a = SomeSeedValue;
a = (a * SomeNumber + AnotherNumber) % SomeLargePrimeNumber;
return a % 65536;
}
If you want to arbitrarily limit the result to 9:
return (catch - temp)%10;
I recommend using a macro constant to abstract the '10' though, otherwise it's a magic number.
Related
I am trying to simulate the propagation of a worm across a network made of 100,000 computers. The simulation itself is very simple and I don't need any help except that for some reason, I am only getting every third random number.
Only the computers whose index modulo 1000 is less than 10 can be infected so when 1000 computers are infected, the program should be done. For some reason, my program only gets 329. When I lower the goal number and check the contents of the array, only every third computer has been changed and it is a consistent pattern. For example at the end of the array, only computers 98001, 98004, 98007, 99002, 99005, 99008 are changed even though the computers in between (98002, 98003, etc.) should be changed as well. The pattern holds all the way to the beginning of the array. When I try to get all 1000 changed, the program goes into an infinite loop and is stuck at 329.
Edit: I just discovered that if I lower the NETSIZE to 10,000 and the goal in the while loop to 100, it doesn't skip anything. Does that mean the problem has something to do with a rounding error? Someone who knows more about C than me must know the answer.
Thanks.
#include <stdio.h>
#include <stdlib.h>
#define NETSIZE 100000
double rand01();
void initNetwork();
unsigned char network[NETSIZE];
int scanrate = 3;
int infectedCount;
int scans;
int ind;
int time;
int main(void) {
initNetwork();
time = 0;
infectedCount = 1;
while (infectedCount < 1000) { //changing 1000 to 329 stops the infinite loop
scans = infectedCount * scanrate;
for (int j = 0; j < scans; j++) {
ind = (int) (rand01() * NETSIZE);
if (network[ind] == 0) {
network[ind] = 1;
infectedCount++;
}
}
time++;
}
for (int k = 0; k < NETSIZE; k++) {
if (network[k] == 1) printf("%d at %d\n", network[k], k);
}
}
double rand01() {
double temp;
temp = (rand() + 0.1) / (RAND_MAX + 1.0);
return temp;
}
void initNetwork() {
for (int i = 0; i < NETSIZE; i++) {
if (i % 1000 < 10) {
network[i] = 0;
} else {
network[i] = 2;
}
}
network[1000] = 1;
}
In the above code, I expect the code to run until the 1000 vulnerable indexes are changed from 0 to 1.
Converting comments into an answer.
What is RAND_MAX on your system? If it is a 15-bit or 16-bit value, you probably aren't getting good enough quantization when converted to double. If it is a 31-bit or bigger number, that (probably) won't be the issue. You need to investigate what values are generated by just the rand01() function with different seeds, plus the multiplication and cast to integer — simply print the results and sort -n | uniq -c to see how uniform the results are.
On my system RAND_MAX is only 32767. Do you think that might be why my results might not be granular enough? Now that you've made me think about it, there would only be 32,767 possible values and my network array is 100,000 possible values. Which corresponds about about the 1/3 results I am getting.
Yes, I think that is very probably the problem. You want 100,000 different values, but your random number generator can only generate about 33,000 different values, which is awfully close to your 1:3 metric. It also explains immediately why you got good results when you reduced the multiplier from 100,000 to 10,000.
You could try:
double rand01(void)
{
assert(RAND_MAX == 32767);
return ((rand() << 15) + rand()) / ((RAND_MAX + 1.0) * (RAND_MAX + 1.0));
}
Or you could use an alternative random number generator — for example, POSIX defines both the drand48() family of functions and
random(), with corresponding seed-setting functions where needed.
Yeah, the problem I am having is that the RAND_MAX value on my system is only 32767 and I am trying to effectively spread that out over 100,000 values which results in about only every third number ever showing up.
In my defense, the person who suggested the rand01() function has a PhD in Computer Science, but I think he ran this code on our school's main computer which probably has a much bigger RAND_MAX value.
#JonathanLeffler deserves credit for this solution.
No idea what I'm doing wrong here. I just need to know how many times "step" can increment until it reaches 1 -- maybe I'm overcomplicating things... I'm fairly new to programming, and I haven't done any for about a year. I don't know if this is relevant but I'm using Xcode 5.0.2 with what I believe is C11 (very new to this language so I have no idea of the version history).
Anyway, the following throws me into an infinite loop with 100% CPU utilisation and energy impact:
int range = 0;
double step = 0.12;
for(int i = step; i <= 1; i += step)
{
range++;
}
"step" is only equal to 0.12 for the purposes of this example; normally it would be user-created input.
Help? :(
Try this:
int range = 0;
double step = 0.12;
for (double d = step; d <= 1.0; d += step) {
range++;
}
You can't assign a floating-point number to an int and get the result you expect, which is what you're doing in int i=step. Very likely, you will get zero for i. Then, when you increment by step, you will get zero again, which explains the infinite loop.
I'm trying to implement a circular buffer in order to average a stream of data points generated by a pressure sensor in C running on an embedded controller. The idea is to store the last N pressure readings in the buffer while maintaining a running sum of the buffer. Average = sum / N. Should be trivial.
However, the average I'm seeing is a value that starts near the pressure reading (I preload the buffer registers with a typical value), but which subsequently trends towards zero. If I also display the sum, it too is dropping asymptotically to zero. If the pressure changes, the average moves away from zero in the direction of the pressure change, but returns to its zero trend as soon as the pressure stabilizes.
If anyone could spot the error I'm making, it would be very helpful.
#define ARRAYSIZE 100
double Sum; // variable for running sum
double Average; // variable for average
double PressureValue[ARRAYSIZE]; // declare value array
int i; // data array index
int main(void) {
while (1)
{
if (i == ARRAYSIZE) i = 0; // test index, reset if it reaches the upper boundary
Sum = Sum - PressureValue[i]; // subtract the old datapoint from running sum
PressureValue[i] = PRESSURE; // replace previous loop datapoint with new data
Sum = Sum + PressureValue[i]; // add back the new current value to the running sum
Average = Sum / ARRAYSIZE; // calculate average value = SUM / ARRAYSIZE
++i; // increment index
} // end while loop
} // end main
The averaging code takes place in an interrupt handler; I'm reading the data from the pressure sensor via I2C with interrupts triggered at the end of each I2C communication phase. During the last phase, after the four bytes comprising the pressure data have been retrieved, they are assembled into a complete reading, and then converted to a decimal reading in PSI contained in the PRESSURE variable.
Obviously , this isn't a direct cut and paste from my code, but I didn't want anyone to have to wade through the whole thing, so I've limited it to just the stuff relevant to figuring the average, and changed the variable names to be more readable. Still, I can't spot what I'm doing wrong.
Thanks for your attention!
Doug G.
I don't see anything obviously wrong with your code, but as you say, you're not providing all of it, so who knows what's happening in the rest of it (in particular, how/if you're initializing i and Sum), but the following works fine for me, which is basically the same algorithm you have:
#include <stdio.h>
#include <stddef.h>
double PressureValue[8];
double Pressures[800];
int main(void) {
const size_t array_size = sizeof(PressureValue) / sizeof(PressureValue[0]);
const size_t num_pressures = sizeof(Pressures) / sizeof(Pressures[0]);
size_t count = 0, i = 0;
double average = 0;
/* Initialize PressureValue to {0, 1, 2, 3, ...} */
for ( size_t n = 0; n < array_size; ++n ) {
PressureValue[n] = n;
}
double sum = ((array_size - 1) / (double) 2) * array_size;
/* Initialize pressures to repeats of PressureValue */
for ( size_t n = 0; n < num_pressures; ++n ) {
Pressures[n] = n % array_size;
}
while ( count < num_pressures ) {
if ( i == array_size )
i = 0;
sum -= PressureValue[i];
PressureValue[i] = Pressures[count++];
sum += PressureValue[i++];
}
average = sum / array_size;
printf("Sum is %f\n", sum);
printf("Counted %zu pressures\n", count);
printf("Average is %f\n", average);
return 0;
}
Outputs:
paul#local:~/src/c/scratch$ ./pressure
Sum is 28.000000
Counted 800 pressures
Average is 3.500000
paul#local:~/src/c/scratch$
Just one more possibility, when you say they are "converted to a decimal reading in PSI contained in the PRESSURE variable", and elsewhere, for that matter, make sure you're not getting things truncated to zero because of integer division. If you've got things "trending to zero" as you're adding more, that's something I'd be immediately suspicious of. A classic error in converting Fahrenheit to Celsius, for instance, would be to write c = (f - 32) * (5 / 9), where that (5 / 9) truncates to zero every time, and always leaves you with c == 0.
Also, as a general rule, I understand that you "didn't want anyone to have to wade through the whole thing", but you'd be surprised how many times the real problem is not in the part of the code that you think it is. This is why it's important to provide an SSCCE to ensure that you can narrow down your code and actually isolate and reproduce the problem. If you try to narrow down your code and find that you can't isolate and reproduce the problem, then it's almost certain that your issue is not being caused by the thing you think is causing it.
It is also possible your code is working exactly as intended. If you are preloading your array with typical values outside of this loop and then running this code you would get the behavior you are describing. If you are preloading the array make sure you are preloading the sum and average otherwise you are essentially measuring gauge pressure with you preloaded value as atmospheric pressure.
I am unable to understand why i am getting runtime error with this code. Problem is every number >=6 can be represented as sum of two prime numbers.
My code is ...... Thanks in advance problem link is http://poj.org/problem?id=2262
#include "stdio.h"
#include "stdlib.h"
#define N 1000000
int main()
{
long int i,j,k;
long int *cp = malloc(1000000*sizeof(long int));
long int *isprime = malloc(1000000*sizeof(long int));
//long int *isprime;
long int num,flag;
//isprime = malloc(2*sizeof(long int));
for(i=0;i<N;i++)
{
isprime[i]=1;
}
j=0;
for(i=2;i<N;i++)
{
if(isprime[i])
{
cp[j] = i;
j++;
for(k=i*i;k<N;k+=i)
{
isprime[k] = 0;
}
}
}
//for(i=0;i<j;i++)
//{
// printf("%d ",cp[i]);
//}
//printf("\n");
while(1)
{
scanf("%ld",&num);
if(num==0) break;
flag = 0;
for(i=0;i<j&&num>cp[i];i++)
{
//printf("%d ",cp[i]);
if(isprime[num-cp[i]])
{
printf("%ld = %ld + %ld\n",num,cp[i],num-cp[i]);
flag = 1;
break;
}
}
if(flag==0)
{
printf("Goldbach's conjecture is wrong.\n");
}
}
free(cp);
free(isprime);
return 0;
}
Two possibilities immediately spring to mind. The first is that the user input may be failing if whatever test harness is being used does not provide any input. Without knowing more detail on the harness, this is a guess at best.
You could check that by hard-coding a value rather than accepting one from standard input.
The other possibility is the rather large memory allocations being done. It may be that you're in a constrained environment which doesn't allow that.
A simple test for that is to drop the value of N (and, by the way, use it rather than the multiple hardcoded 1000000 figures in your malloc calls). A better way would be to check the return value from malloc to ensure it's not NULL. That should be done anyway.
And, aside from that, you may want to check your Eratosthenes Sieve code. The first item that should be marked non-prime for the prime i is i + i rather than i * i as you have. I think it should be:
for (k = i + i; k < N; k += i)
The mathematical algorithm is actually okay since any multiple of N less than N * N will already have been marked non-prime by virtue of the fact it's a multiple of one of the primes previously checked.
Your problem lies with integer overflow. At the point where N becomes 46_349, N * N is 2_148_229_801 which, if you have a 32-bit two's complement integer (maximum value of 2_147_483_647), will wrap around to -2_146_737_495.
When that happens, the loop keeps going since that negative number is still less than your limit, but using it as an array index is, shall we say, inadvisable :-)
The reason it works with i + i is because your limit is well short of INT_MAX / 2 so no overflow happens there.
If you want to make sure that this won't be a problem if you get up near INT_MAX / 2, you can use something like:
for (k = i + i; (k < N) && (k > i); k += i)
That extra check on k should catch the wraparound event, provided your wrapping follows the "normal" behaviour - technically, I think it's undefined behaviour to wrap but most implementations simply wrap two positives back to a negative due to the two's complement nature. Be aware then that this is actually non-portable, but what that means in practice is that it will only work on 99.999% of machines out there :-)
But, if you're a stickler for portability, there are better ways to prevent overflow in the first place. I won't go into them here but to say they involve subtracting one of the terms being summed from MAX_INT and comparing it to the other term being summed.
The only way I can get this to give an error is if I enter a value greater than 1000000 or less than 1 to the scanf().
Like this:
ubuntu#amrith:/tmp$ ./x
183475666
Segmentation fault (core dumped)
ubuntu#amrith:/tmp$
But the reason for that should be obvious. Other than that, this code looks good.
Just trying to find what went wrong!
If the sizeof(long int) is 4 bytes for the OS that you are using, then it makes this problem.
In the code:
for(k=i*i;k<N;k+=i)
{
isprime[k] = 0;
}
Here, when you do k = i*i, for large values if i, the value of k goes beyond 4 bytesand get truncated which may result in negative numbers and so, the condition k<N is satisfied but with a negative number :). So you get a segmentation fault there.
It's good that you need only i+i, but if you need to increase the limit, take care of this problem.
char byte_to_ascii(char value_to_convert, volatile char *converted_value) {
if (value_to_convert < 10) {
return (value_to_convert + 48);
} else {
char a = value_to_convert / 10;
double x = fmod((double)value_to_convert, 10.0);
char b = (char)x;
a = a + 48;
b = b + 48;
*converted_value = a;
*(converted_value+1) = b;
return 0;
}
}
The purpose of this function is to take an unsigned char value of 0 through 99 and return either it's ascii equivalent in the case it is 0-9 or manipulate a small global character array that can be referenced from the calling code following function completion.
I ask this question because two compilers from the same vendor interpret this code in different ways.
This code was written as a way to parse address bytes sent via RS485 into strings that can easily be passed to a send-lcd-string function.
This code is written for the PIC18 architecture (8 bit uC).
The problem is that the free/evaluation version of a particular compiler generates perfect assembly code that works while suffering a performance hit, but the paid and supposedly superior compiler generates code more efficiently at the expense of being able reference the addresses of all my byte arrays used to drive the graphics on my lcd display.
I know I'm putting lots of mud in the water by using a proprietary compiler for a less than typical architecture, but I hope someone out there has some suggestions.
Thanks.
I would definitely avoid using floating point anything on a PIC. And I would -try not to- use any divisions. How many times do you see sending a non-ascii char to the LCD? Can you save it to the LCD's memory and then call it by it's memory position?
Here's what a divide by 10 looks like in my code, note the 17 cycles it needs to complete. Think about how long that will take, and make sure there is nothing else waiting on this.
61: q = d2 / 10;
01520 90482E mov.b [0x001c+10],0x0000
01522 FB8000 ze 0x0000,0x0000
01524 2000A2 mov.w #0xa,0x0004
01526 090011 repeat #17
01528 D88002 div.uw 0x0000,0x0004
0152A 984F00 mov.b 0x0000,[0x001c+8]
If you do a floating point anything in your code, look in the program memory after you've compiled it, on the Symbolic tab (so you can actually read it) and look for the floating point code that will need to be included. You'll find it up near the top (depending on your code), soon(ish) after the _reset label.
Mine starts at line number 223 and memory address of 001BC with _ floatsisf, continues through several additional labels (_fpack, _divsf3, etc) and ends in _funpack, last line at 535 and memory address 0042C. If you can handle (42C-1BC = 0x270 =) 624 bytes of lost program space, great, but some chips have just 2k of space and that's not an option.
Instead of floating point, if it's possible, try to use fixed point arithmetic, in base 2.
As far as not being able to reference all the byte arrays in your LCD, have you checked to make sure that you're not trying to send a null (which is a fine address) but it get's stopped by code checking for the end of an ascii string? (it's happened to me before).
modulo and integer division can be very very expensive. I have do not know about your particular architecture, but my guess it is expensive there as well.
If you need both, division and modulo, do one of them and get the other one by multiplication/difference.
q =p/10;
r = p - q*10;
I'd probably write that as:
char byte_to_ascii(char value_to_convert, volatile char *converted_value)
{
if (value_to_convert < 10) {
return value_to_convert + '0';
} else {
converted_value[0] = (value_to_convert / 10) + '0';
converted_value[1] = (value_to_convert % 10) + '0';
return 0;
}
}
Is it poor form to convert to floating, call fmod, and convert to integer, instead of just using the % operator? I would say yes. There are more readable ways to slow down a program to meet some timing requirement, for example sleeping in a for loop. No matter what compiler or what tweaking of assembly code or whatever else, this is a highly obfuscated way to control the execution speed of your program, and I call it poor form.
If perfect assembly code means that it works right but it's even slower than the conversions to floating point and back, then use integers and sleep in a for loop.
As for the imperfect assembly code, what's the problem? "at the expense of being able reference the addresses of all my byte arrays"? It looks like type char* is working in your code, so it seems that you can address all your byte arrays the way the C standard says you can. What's the problem?
Frankly, I would say yes..
If you wanted b to be the remainder, either use MOD or roll-your-own:
char a = value_to_convert / 10;
char b = value_to_convert - (10 * a);
Conversion to/from floats is never the way to do things, unless your values really are floats.
Furthermore, I would strongly recommend to stick to the convention of explicitly referring to your datatypes as 'signed' or 'unsigned', and leave the bare 'char' for when it actually is a character (part of a string). You are passing in raw data, which I feel should be an unsigned char (assuming of course, that the source is unsigned!). It is easy to forget if something should be signed/unsigned, and with a bare char, you'll get all sorts of roll-over errors.
Most 8-bit micros take forever for a multiply (and more than forever for a divide), so try and minimise these.
Hope this helps..
The code seems to be doing two very different things, depending on whether it's given a number in the range 0-9 or 10-99. For that reason, I would say that this function is written in poor form: I would split your function into two functions.
Since we're discussing divisions by 10 here..
This is my take. It only simple operations and does not even need wide registers.
unsigned char divide_by_10 (unsigned char value)
{
unsigned char q;
q = (value>>1) + (value>>2);
q += (q>>4);
q >>= 3;
value -= (q<<3)+q+q;
return q+((value+6)>>4);
}
Cheers,
Nils
It is typical for optimizers to do unwanted thingies from time to time if you poke around in the internals.
Is your converted_value a global value or otherwise assigned in such a fashion that the compiler knows not to touch it?
PIC's don't like doing pointer arithmetic.
As Windows programmer points out, use the mod operator (see below.)
char byte_to_ascii(char value_to_convert, volatile char *converted_value) {
if (value_to_convert < 10) {
return (value_to_convert + 48);
} else {
char a = value_to_convert / 10;
char b = value_TO_convert%10;
a = a + 48;
b = b + 48;
*converted_value = a;
*(converted_value+1) = b;
return 0;
}
}
Yes, I believe that your function:
char byte_to_ascii(char value_to_convert, volatile char *converted_value) {
if (value_to_convert < 10) {
return (value_to_convert + 48);
} else {
char a = value_to_convert / 10;
double x = fmod((double)value_to_convert, 10.0);
char b = (char)x;
a = a + 48;
b = b + 48;
*converted_value = a;
*(converted_value+1) = b;
return 0;
}
}
is in poor form:
Don't use decimal numbers for ASCII chars, use the character, i.e. '#' instead of 0x40.
There is no need for using the fmode function.
Here is my example:
// Assuming 8-bit octet
char value;
char largeValue;
value = value_to_convert / 100;
value += '0';
converted_value[0] = value;
largeValue = value_to_convert - value * 100;
value = largeValue / 10;
value += '0';
converted_value[1] = value;
largeValue = largeValue - value * 10;
value += '0';
converted_value[2] = value;
converted_value[3] = '\0'; // Null terminator.
Since there are only 3 digits, I decided to unroll the loop. There are no branches to interrupt the prefetching of instructions. No floating point exceptions, just integer arithmetic.
If you leading spaces instead of zeros, you can try this:
value = (value == 0) ? ' ' : value + '0';
Just to be a nitwitt, but multiple return statements from the same function can be considered bad form (MISRA).
Also, some of the discussions above are on the limit of permature optimizations. Some tasks must be left to the compiler. However, in such a minimalistic embedded environment, these tricks may be valid still.