I'm looking at someone else's code and trying to figure out the logic behind what they wrote. What would one use the following random number calculation for?
return ( ((rand() % 10000)+1) <= Rate * 100);
Rate here is being used for a user-specified value representing an overall percentage of when a certain event occurs.
The left part of the expression returns a random number between 1 and 10,000 (due to the + 1; otherwise it would be between 0 and 9,999).
Rate can then be used to determine the effective chance of the expression being true. The higher Rate is, the higher the chance of returning true.
Since Rate is multiplied with 100, you're able to determine the Rate using 0 to 100 (essentially percentages) with Rate = 0 never and Rate = 100 always returning true.
To generate a random integer between 1 and 10000 inclusive. As for the comparison with Rate*100 who can say as you do not specify what this means.
Related
I need to calculate the time complexity of the f3 function:
My problem is that I can't succeed on calculate how many time I can appley sqrt() function on n till its lower than 1: n^0.5^k < 1
I can assume that the time complexity of sqrt() is 1.
any ideas how can I get the k value out of n^0.5^k < 1 ? if I succeed that, then I think value the sum of the series: n/2, (n^0.5)/2, (n^0.5^2)/2,... would be easier.
I will show the lower and upper bound.
First we compute the cost of g3.
Take for example, n = 2^16.
How many iterations we make in the for loop?
i=2^0, i=2^1, i=2^2, i=2^3... < 2^16
More or less, that would be 16 steps. So the cost of g3 is O(log(n)).
Now lets try to compute f3. Since it's using g3 inside the loop, it would go as follows:
log(n) + log(n^(1/2)) + log(n^(1/4)) + log(n^(1/8)) + ...
That's for sure greater than log(n), so we could take log(n) as the lower bound.
Now, in order to compute the upper bound we have to think, how many iterations does the loop do?
Take again 2^16 as an example:
2^16, 2^16^(1/2), 2^16^(1/4), 2^16^(1/8), 2^16^(1/16),
That turns out to be:
2^16, 2^8, 2^4, 2^2, 2^1
And in the next iteration we would stop because sqrt(2) rounds to 1.
So in general, if n=2^2^k, we make k iterations. That's log(log(n)). That means we could say log(n)*log(log(n)) as the upper bound.
There is probably a more adjusted solution but this should be pretty accurate.
I want to find "significant" changes in a cell array in MATLAB for when I have a movement.
E.g. I have YT which represents movements in a yaw presentation for a face interaction. YT can change based on an interaction from anywhere upwards of 80x1 to 400x1. The first few lines might be
YT = {-7 -8 -8 -8 -8 -9 -9 -9 -6 ...}
I would like to record the following
Over the entire cell array;
1) Count the number of high and low peaks
I can do this with findpeak but not for low peaks?*
2) Measure the difference between each peak -
For this example, peaks -9 and -6 so difference of +3 between those. So report 1 peak change of +3. At the moment I am only interested in changes of +/- 3, but this might change, so I will need a threshold?
and then over X number of cells (repeating for the cell array)
3) count number of changes - for this example, 3 changes
3) count number of significant changes - for this example, 1 changes of -/+3
4) describe the change - 1 change of -1, 1 change of -1, 1 change of +3
Any help would be appreciated, bit of a MATLAB noob.
Thanks!
1) Finding negative peaks is the same as finding positive ones - all you need to do is multiply the sequence by -1 and then findpeaks again
2) If you simply want the differences, then you could subtract the vectors of the positive and negative peaks (possibly offset by one if you want differences in both directions). Something like pospeaks-negpeaks would do one side. You'd need to identify whether the positive or negative peak was first (use the loc return from findpeaks to determine this), and then do pospeaks(1:end-1)-negpeaks(2:end) or vice versa as appropriate.
[edit]As pointed out in your comment, the above assumes that pospeaks and negpeaks are the same length. I shouldn't have been so lazy! The code might be better written as:
if (length(pospeaks)>length(negpeaks))
% Starts and ends with a positive peak
neg_diffs=pospeaks(1:end-1)-negpeaks;
pos_diffs=negpeaks-pospeaks(2:end);
elseif (length(pospeaks)<length(negpeaks))
% Starts and ends with a negative peak
pos_diffs=negpeaks(1:end-1)-pospeaks;
neg_diffs=pospeaks-negpeaks(1:end-1);
elseif posloc<negloc
% Starts with a positive peak, and ends with a negative one
neg_diffs=pospeaks-negpeaks;
pos_diffs=pospeaks(2:end)-negpeaks(1:end-1);
else
% Starts with a negative peak, and ends with a positive one
pos_diffs=negpeaks-pospeaks;
neg_diffs=negpeaks(2:end)-pospeaks(1:end-1);
end
I'm sure that could be coded more effectively, but I can't think just now how to write it more compactly. posloc and negloc are the location returns from findpeaks.[/edit]
For (3) to (5) it is easier to record the differences between samples: changes=[YT{2:end}]-[YT{1:end-1}];
3) To count changes, count the number of non-zeros in the difference between adjacent elements: sum(changes~=0)
4) You don't define what you mean by "significant changes", but the test is almost identical to 3) sum(abs(changes)>=3)
5) It is simply changes(changes~=0)
I would suggest diff is the command which can provide the basis of a solution to all your problems (prior converting the cell to an array with cell2mat). It outputs the difference between adjacent values along an array:
1) You'd have to define what a 'peak' is but at a guess:
YT = cell2mat(YT); % convert cell to array
change = diff(YT); % get diffs
highp = sum(change >= 3); % high peak threshold
lowp = sum(change <= -3); % low peak threshold
2) diff(cell2mat(YT)) provides this.
3)
YT = cell2mat(YT); % convert cell to array
change = diff(YT); % get diffs
count = sum(change~=0);
4) Seems to be answered in the other points?
I have a 32.768 kHz oscillator which produces a 1-Hz pulse. I'm measuring this pulse with a 40MHz clock. I am trying to measure the actual frequency of the oscillator by comparing the expected results with the obtained one.
I cannot change the period that I'm measuring, it has to be 1-Hz (1s).
I cannot use float, double or types larger than uint32.
I also need the first digit after the integer part (like 32768.1 Hz).
Without the constraints the solution would be like:
computedFreq = (uint32) ( (float32)32768u / ( ( (float32)measuredPeriod / (float32)40,000,000 ) / (float32)10u ) );
or
computedFreq = ( 32768*10*40,000,000 ) / measuredPeriod;
So for a measured period of 40,008,312 the result will be 327611.
How can this be achieved while satisfying the constraints?
Your problem is that measured range goes up to 40010000 Hz, while you are only interested in 20000 Hz range. So the solution is to limit the range.
You can do this with linear interpolation using 2 points.
Select 2 input values. Min/max points might do:
inMin = 40,000,000 - 10,000
inMax = 40,000,000 + 10,000
Precalculate respective output values using your formula (values here are rough values, calculate your own): You can store these as constants in your code.
outMin = ( 32768*10*40,000,000 ) / inMin = 327761
outMax = ( 32768*10*40,000,000 ) / inMax = 327598
Notice how max is smaller than min, due the nature of your formula. This is important when selecting types below.
Use linear interpolation to calculate result using both previous points:
out = (in - inMin) * (outMax - outMin) / (inMax - inMin) + outMin
You have to use signed integers for this, because (outMax - outMin) is negative.
Upper limit of the multiplication is (inMax - inMin) * (outMax - outMin), which should fit into int32.
You can pick any 2 points, but you should pick ones that will not produce too big values to overflow on multiplication. Also, if points are too near each other, answer may be less accurate.
If you you have extra precision to spare, you could use bigger multiplier than 10 on outMin/outMax and round afterwards to keep more precision.
Note that 32768 * 10 * 40000000 = 3200000000 * 2^12.
You can use this fact in order to approximate the frequency as follows:
computedFreq = (3200000000/measuredPeriod) << 12;
UPDATE:
I understand that 39990000 <= measuredPeriod <= 40010000.
A better way to approximate the frequency under this restriction would be:
computedFreq = 327761-(measuredPeriod-39990000)/122;
Hi there I am currently trying to create a simple game in c based around a map with different ai players.
I've came along to program the calculations to figure out an amount of health lost and although I am sure my math behind it is correct the implemtnation in c doesn't seem to be working! I might have missed a simple point but I'll put the extract of code which isn't working as expected.
random1 = Numbergen(50);
cal1 = (100 - random1)/100;
random2 = Numbergen(50);
cal2 = (100 - random2) / 100;
PtrPlayer[attacker].health = (double)(PtrPlayer[attacker].health * cal1);
PtrPlayer[ncount].health = (double)(PtrPlayer[ncount].health * cal2);
printf("There was a battle but both players drawed and retreated.\n");
return 1;
Numbergen is a function that calculates a random number based on a time seed, 50 is the maximum number I want it to return with.
cal1 and 2 should store a decimal number for example 0.75 to take off 25% health and that's what the cal calculations should be doing however when debugging they are showing a value of zero no matter what the random number is.
This should work by taking the random number lets say 25 way from 100 to leave 75, it then divides by 100 to get a decimal multiplier which can then be used to reduce the health by 25%. Health starts at 100 so for example it will result in 100*0.75 which should leave me with 75 health but instead cal one stores 0 and as a result the health goes down to zero.
To be clear cal1 and 2 are both floats to allow for decimal places.
If anyone can point out where I might have gone wrong I will be so grateful!
If I've missed out something important then please let me know and I'll try and explain.
Also please note I am only a beginner in programming so please don't hit me with super complex code!
As requested random1 and 2 are both ints
PtrPlayer[].health is set as ints
cal1 and 2 are set as floats
cal1 = (100 - random1)/100;
Since random1 is an int, and 100 is an int, (100 - random1) is also an int. When you use the / operator on two integer operands, a truncating integer division is performed.
If you want floating-point division, convert at least one side of / to a floating-point type :
cal1 = (100 - random1) / 100.0f;
// float literal ^^^^^^
... or...
cal1 = (float)(100 - random1) / 100;
Simply converting the result of the division would have no effect, as C expressions' types are determined strictly from the inside out.
Just try changing either of the two 100 as 100.0
100.0 - random1
100.0 - random2
Or
(100 - random1)/100.0
(100 - random2)/100.0
This is the easiest option.
For one of my homework problems, we had to write a function that creates an array containing n random numbers between 1 and 365. (Done). Then, check if any of these n birthdays are identical. Is there a shorter way to do this than doing several loops or several logical expressions?
Thank you!
CODE SO FAR, NOT DONE YET!!
function = [prob] bdayprob(N,n)
N = input('Please enter the number of experiments performed: N = ');
n = input('Please enter the sample size: n = ');
count = 0;
for(i=1:n)
x(i) = randi(365);
if(x(i)== x)
count = count + 1
end
return
If I'm interpreting your question properly, you want to check to see if generating n integers or days results in n unique numbers. Given your current knowledge in MATLAB, it's as simple as doing:
n = 30; %// Define sample size
N = 10; %// Define number of trials
%// Define logical array where each location tells you whether
%// birthdays were repeated for a trial
check = false(1, N);
%// For each trial...
for idx = 1 : N
%// Generate sample size random numbers
days = randi(365, n, 1);
%// Check to see if the total number of unique birthdays
%// are equal to the sample size
check(idx) = numel(unique(days)) == n;
end
Woah! Let's go through the code slowly shall we? We first define the sample size and the number of trials. We then specify a logical array where each location tells you whether or not there were repeated birthdays generated for that trial. Now, we start with a loop where for each trial, we generate random numbers from 1 to 365 that is of n or sample size long. We then use unique and figure out all unique integers that were generated from this random generation. If all of the birthdays are unique, then the total number of unique birthdays generated should equal the sample size. If we don't, then we have repeats. For example, if we generated a sample of [1 1 1 2 2], the output of unique would be [1 2], and the total number of unique elements is 2. Since this doesn't equal 5 or the sample size, then we know that the birthdays generated weren't unique. However, if we had [1 3 4 6 7], unique would give the same output, and since the output length is the same as the sample size, we know that all of the days are unique.
So, we check to see if this number is equal to the sample size for each iteration. If it is, then we output true. If not, we output false. When I run this code on my end, this is what I get for check. I set the sample size to 30 and the number of trials to be 10.
check =
0 0 1 1 0 0 0 0 1 0
Take note that if you increase the sample size, there is a higher probability that you will get duplicates, because randi can be considered as sampling with replacement. Therefore, the larger the sample size, the higher the chance of getting duplicate values. I made the sample size small on purpose so that we can see that it's possible to get unique days. However, if you set it to something like 100, or 200, you will most likely get check to be all false as there will most likely be duplicates per trial.
Here are some more approaches that avoid loops. Let
n = 20; %// define sample size
x = randi(365,n,1); %// generate n values between 1 and 365
Any of the following code snippets returns true (or 1) if there are two identical values in x, and false (or 0) otherwise:
Sort and then check if any two consecutive elements are the same:
result = any(diff(sort(x))==0);
Do all pairwise comparisons manually; remove self-pairs and duplicate pairs; and check if any of the remaining comparisons is true:
result = nnz(tril(bsxfun(#eq, x, x.'),-1))>0;
Compute the distance between distinct values, considering each pair just once, and then check if any distance is 0:
result = any(pdist(x(:))==0);
Find the number of occurrences of the most common value (mode):
[~, occurs] = mode(x);
result = occurs>1;
I don't know if I'm supposed to solve the problem for you, but perhaps a few hints may lead you in the right direction (besides I'm not a matlab expert so it will be in general terms):
Maybe not, but you have to ask yourself what they expect of you. The solution you propose requires you to loop through the array in two nested loops which will mean n*(n-1)/2 times through the loop (ie quadratic time complexity).
There are a number of ways you can improve the time complexity of the problem. The most straightforward would be to have a 365 element table where you can keep track if a particular number has been seen yet - which would require only a single loop (ie linear time complexity), but perhaps that's not what they're looking for either. But maybe that solution is a little bit ad-hoc? What we're basically looking for is a fast lookup if a particular number has been seen before - there exists more memory efficient structures that allows look up in O(1) time and O(log n) time (if you know these you have an arsenal of tools to use).
Then of course you could use the pidgeonhole principle to provide the answer much faster in some special cases (remember that you only asked to determine whether two or more numbers are equal or not).