Nested IF...THEN...ELSE in GW-BASIC - if-statement

I use following block of code to test some conditions in gw-basic program.
IF Average >= 80 AND Average <= 100 THEN Grade$ = "A"
IF Average >= 70 AND Average <= 79 THEN Grade$ = "B"
IF Average >= 60 AND Average <= 69 THEN Grade$ = "C"
IF Average >= 50 AND Average <= 59 THEN Grade$ = "D"
IF Average >= 40 AND Average <= 49 THEN Grade$ = "E" ELSE Grade$ = "F"
PRINT "Average is: ", Average
PRINT "Grade is: ", Grade$
It always prints Grade is: F whatever is the value of Àverage.
What is the error in this gw-basic program?

IF Average >= 40 AND Average <= 49 THEN Grade$ = "E" ELSE Grade$ = "F"
Because this IF THEN ELSE line will always assign a value to Grade$ (no matter the content of Average), all of the previous IF THEN's don't count for much.
The solution however is very, very simple. Don't use the ELSE clause and give the Grade$ a default value of "F" to start with. That way, only if all of those conditions evaluate to false, the program will return "Grade is: F".
Grade$ = "F"
IF Average >= 80 AND Average <= 100 THEN Grade$ = "A"
IF Average >= 70 AND Average <= 79 THEN Grade$ = "B"
IF Average >= 60 AND Average <= 69 THEN Grade$ = "C"
IF Average >= 50 AND Average <= 59 THEN Grade$ = "D"
IF Average >= 40 AND Average <= 49 THEN Grade$ = "E"
PRINT "Average is: ", Average
PRINT "Grade is: ", Grade$

suppose print average line is line number 70, so after each line except the ELSE line write GOTO 70. Try if that works.

Related

How do can I get rid of the blank lines that are created c++?

Edit:
Thank you all for the quick and helpful replies. I got it working now. It was because I had to reset the counter.
I have come to ask for help as my professor is not giving me the help I need. I am new to c++ and I am trying to program a program that displays all the integers from 1 to 100 that are divisible by 6 or 7, but not both. and I have to display 5 numbers per row. I got it working except I have blank lines forming in certain areas. I don't know if it's because of how I set up the counter or what.
Here is what I got.
#include <iostream>
using namespace std;
int main()
{
int counter = 0; // Counter for creating new lines after 5 numbers
for (int numRange = 1; numRange <= 100; ++numRange) // Starts the loop of number 1 to 100
{
if (numRange % 6 == 0 || numRange % 7 == 0) // Makes the numbers divisible by 6 and 7
{
cout << numRange << " "; // Displays the output of the divisible numbers
counter++; // Starts the counter
}
if (counter % 5 == 0) // using the counter to create new lines after 5 numbers displayed
{
cout << endl; // Creates a new line
}
}
return 0;
}
This is what is outputted:
6 7 12 14 18
21 24 28 30 35
36 42 48 49 54
56 60 63 66 70
72 77 78 84 90
91 96 98
and this is what it's supposed to look like
6 7 12 14 18
21 24 28 30 35
36 48 49 54 56
60 63 66 70 72
77 78 90 91 96
98
The problem that you're seeing is due to the fact that you are checking for "5 outputs" on every loop, rather than only on ones where a number has been output! So, to fix this issue (there are others), put the counter % 5 == 0 test inside the preceding if block:
for (int numRange = 1; numRange <= 100; ++numRange) // Starts the loop of number 1 to 100
{
if (numRange % 6 == 0 || numRange % 7 == 0) // Makes the numbers divisible by 6 and 7
{
cout << numRange << " "; // Displays the output of the divisible numbers
counter++; // Increments the counter
if (counter % 5 == 0) // Only need this if we have done some output!
{
cout << endl; // Creates a new line
}
}
}
Another problem is that, in this requirement:
that are divisible by 6 or 7, but not both
your code doesn't check for the "but not both" part (but that's not the 'title' question, and I'm not going to do all your homework in one fell swoop).

Getting a set of random number between 2 numbers that have a certain mean. [duplicate]

This question already has answers here:
Get `n` random values between 2 numbers having average `x`
(5 answers)
Closed 6 years ago.
Problem: Getting a set of random numbers between two values that will have a certain mean value.
Let say we getting n number of random number where the number will be between 1 and 100. We have a mean of 25.
My first approach is to have 2 modes where we have aboveMean and belowMean where the first random number is the initial range 1 and 100. Every subsequent number will check the total sum. If the total sum is above the mean, we go to case aboveMean which is then get a random number between 1 and 25. If the total sum is below the mean, we do case belowMean then get a random number between 26 and 100.
I need some idea on how to approach this problem beside the crude get a random number to add it to the total then get the average. If it above the mean in question, we get a random number below the mean and so forth. While it does work, doesn't seem to be the best method.
I'm guessing I should brush up on probability to approach this random number generator.
Let us divide the range into left and right portions. Use a value from the portion at a frequency corresponding to the relative width of the other half.
int Leruce_rand(int min, int mean, int max) {
int r = rand()%(max - min + 1);
if (r < mean) {
// find number in right half
return rand()%(max - mean + 1) + mean;
} else {
// find number in left half
return rand()%(mean - min) + min;
}
Assumes mean is part of the right half. This quick solution likely has small bias.
Given OP's values, roughly, the average of the left half is 12.5 and called 75% of the time. Average of the right is 62.5 called 25% of the time: average 25.
This approach differs from OP's which "Every subsequent number will check the total sum. If the total sum is above the mean, we go to case aboveMean which is then get a random number between 1 and 25." As that absolutely prevents a set of occurrences above or below the mean. With RNG, the value generated should not be biased on the history of previous generated values.
There's literally an infinite number of ways to achieve this. For instance, generate 3 random numbers between 1 and 100 (std::uniform_int_distribution) and take the minimum of those (std::min(a,b,c)).
Obviously, for a mean of 75 you'll need to pick the maximum of 3 numbers.
The benefit of this method is that each outcome is independent of the previous ones. It's completely random.
Take some good distribution and use it. Say, Binomial distribution. Use B(99,24/99),
so sampled values are in the range 0...99, with parameter p equal to 24/99.
So if you have routine which sample from B, then all you need is to add 1
to be in he range 1...100
Mean value for binomial would be p*n, in this case equal to 24. Because you're adding 1, your mean value would be 25 as required. C++11 has binomial RNG in the
standard library
Some code (not tested)
#include <iostream>
#include <random>
int main() {
std::default_random_engine generator;
std::binomial_distribution<int> distribution(99, double(24)/double(99));
for (int i=0; i != 1000; ++i) {
int number = distribution(generator) + 1;
std::cout << number << std::endl;
}
return 0;
}
Assume a fair random(a,b) function (this question should not be about which random function is better) then simply just restrcting ithe ranges that is piced from should be a good start, like;
const int desiredCount = 16;
const int deiredMean = 25;
int sumValues = random(a,b);
int count = 1;
while (count < desriredCount - 1) {
int mean = sumValue/count;
int nextValue = 0;
if (mean < desiredMean) // Too small, reduce probablity of smaller numbers
nextValue = random(a+(desiredMean-mean)/(desriredCount-count),b);
else //too large, reduce probability of larger numbers
nextValue = random(a,b-(mean-desiredMean)/(desriredCount-count));
sumValue += nextValue;
count += 1;
}
int lastValue = desiredMean*desriredCount - sumValue/count;
sumValue += lastValue;
count += 1;
Note: The above is not tested, and my thinking is that the trimming of the upper and lower bound may not be sufficently aggressive to do the trick, but I hope that i will get you going.
Some boundary conditions, such as if you only want 2 numbers and a means of 25 from numbers between 0 and 100, the initial random number cannot be larger than 50, since that makes it impossible to pick the second (last) number -- so if you want the algo to give you exact mean values under all circumstances, then a bit more tweaking is needed.
OP's wants a set of numbers meeting certain criteria.
Consider generating all possible sets of n numbers in the range [min max] and then eliminating all sets but those with the desired mean. Now randomly select one of those sets. This would meet OP's goal and IMO would pass fair randomness tests. Yet this direct approach is potentially a huge task.
Alternatively, randomly generate lots of sets until one is found that meets the mean test.
The below meets OP's requirement of a specified mean without directly biasing the random numbers selected. Certainly not an efficient method when the desired mean is far from the min/max average.
#include <stdio.h>
#include <stdlib.h>
void L_set(int *set, size_t n, int min, int mean, int max) {
assert(n > 0);
assert(min >= 0);
assert(mean >= min);
assert(max >= mean);
size_t i;
long long diff;
long long sum_target = n;
unsigned long long loop = 0;
sum_target *= mean;
int range = max - min + 1;
do {
loop++;
long long sum = 0;
for (i = 1; i < n; i++) {
set[i] = rand() % range + min;
sum += set[i];
}
diff = sum_target - sum; // What does the final number need to be?
} while (diff < min || diff > max);
set[0] = (int) diff;
printf("n:%zu min:%d mean:%2d max:%3d loop:%6llu {", n, min, mean, max, loop);
for (i = 0; i < n; i++) {
printf("%3d,", set[i]);
}
printf("}\n");
fflush(stdout);
}
int main(void) {
int set[1000];
L_set(set, 10, 1, 2, 4);
L_set(set, 16, 1, 50, 100);
L_set(set, 16, 1, 25, 100);
L_set(set, 16, 1, 20, 100);
return 0;
}
Output
n:10 min:1 mean: 2 max: 4 loop: 1 { 4, 2, 4, 3, 2, 1, 1, 1, 1, 1,}
n:16 min:1 mean:50 max:100 loop: 2 { 45, 81, 24, 50, 93, 65, 70, 52, 28, 91, 25, 36, 21, 45, 11, 63,}
n:16 min:1 mean:25 max:100 loop: 3257 { 52, 1, 15, 70, 66, 30, 1, 4, 26, 1, 16, 4, 48, 42, 19, 5,}
n:16 min:1 mean:20 max:100 loop:192974 { 24, 10, 13, 3, 3, 53, 22, 12, 29, 1, 7, 6, 90, 11, 20, 16,}
you have to go into some probabilities theory. there are a lot of methods to judge on random sequence. for example if you lower the deviation you will get triangle-looking-on-a-graph sequence, which can in the end be proven not trully random. so there is not really much choice than getting random generator and discarding the sequences you don't like.
EDIT: this generates numbers in the range 1..100 with a theoretical mean of 25.25. It does this by using a random modulus in the range 1..100. Note that the required mean is 25, which is not exactly a quarter of the range 1..100.
OP wanted a way of varying the next number chosen according to whether the mean is less than or more than 25, but that lends some predictabilty - if the mean is more than 25 then you know the next "random" number will be less than 25.
The random calculation in the code is a very simple one line.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define RUNS 10000000
#define MAXN 100
int main() {
int n, i, sum = 0, min = MAXN, max = 0;
int freq[MAXN+1] = {0};
srand((unsigned)time(NULL));
for(i = 0; i < RUNS; i++) {
n = 1 + rand() % (1 + rand() % 100); // average modulus is (1 + MAX) / 2
if(max < n) {
max = n; // check that whole range is picked
}
if(min > n) {
min = n;
}
freq[n]++; // keep a tally
sum += n;
}
// show statistis
printf("Mean = %f, min = %d, max = %d\n", (double)sum / RUNS, min, max);
for(n = MAXN; n > 0; n--) {
printf("%3d ", n);
for(i = (freq[n] + 5000) / 10000; i > 0; i--) {
printf("|");
}
printf("\n");
}
return 0;
}
Program output showing distribution / 10000:
Mean = 25.728128, min = 1, max = 100
100
99
98
97
96 |
95 |
94 |
93 |
92 |
91 |
90 |
89 |
88 |
87 |
86 ||
85 ||
84 ||
83 ||
82 ||
81 ||
80 ||
79 ||
78 |||
77 |||
76 |||
75 |||
74 |||
73 |||
72 |||
71 ||||
70 ||||
69 ||||
68 ||||
67 ||||
66 ||||
65 ||||
64 |||||
63 |||||
62 |||||
61 |||||
60 |||||
59 |||||
58 ||||||
57 ||||||
56 ||||||
55 ||||||
54 ||||||
53 ||||||
52 |||||||
51 |||||||
50 |||||||
49 |||||||
48 |||||||
47 ||||||||
46 ||||||||
45 ||||||||
44 ||||||||
43 |||||||||
42 |||||||||
41 |||||||||
40 |||||||||
39 ||||||||||
38 ||||||||||
37 ||||||||||
36 ||||||||||
35 |||||||||||
34 |||||||||||
33 |||||||||||
32 ||||||||||||
31 ||||||||||||
30 ||||||||||||
29 |||||||||||||
28 |||||||||||||
27 |||||||||||||
26 ||||||||||||||
25 ||||||||||||||
24 ||||||||||||||
23 |||||||||||||||
22 |||||||||||||||
21 ||||||||||||||||
20 ||||||||||||||||
19 |||||||||||||||||
18 |||||||||||||||||
17 ||||||||||||||||||
16 |||||||||||||||||||
15 |||||||||||||||||||
14 ||||||||||||||||||||
13 |||||||||||||||||||||
12 ||||||||||||||||||||||
11 |||||||||||||||||||||||
10 ||||||||||||||||||||||||
9 |||||||||||||||||||||||||
8 ||||||||||||||||||||||||||
7 |||||||||||||||||||||||||||
6 |||||||||||||||||||||||||||||
5 |||||||||||||||||||||||||||||||
4 |||||||||||||||||||||||||||||||||
3 |||||||||||||||||||||||||||||||||||||
2 ||||||||||||||||||||||||||||||||||||||||||
1 ||||||||||||||||||||||||||||||||||||||||||||||||||||
OP did not state what kind of distribution was wanted, for example two straight lines pivoting at 25, or perhaps equal distribution each side of 25. However this solution is very simple to implement.

How does Rand work when starting at a number(36) with a max of 75

I am creating a random number generator and whenever I run the current code block I always get a few numbers that go over the intended limit. The way it works is that I have a set of numbers that are randomly generated that go from 36-75, With adjusted numbers that are 5 higher and 5 lower than the original number. For example I will end up with numbers above 75. The highest being 105.
Here is just one of the 6 numbers.
//Displays picks for Number 4
pick4 = (rand() % 75) + 36;
if (pick4 == pick3)
pick4 = (rand() % 75) + 36;
if (pick4 + 5 < 75 + 1)
{
if (pick4 - 5 > 0)
{
adjHighPick4 = pick4 + 5;
adjLowPick4 = pick4 - 5;
}
}
When you want to get a random integer from A to B, you just need a random integer from 0 to B-A, to which you add A. So, instead of rand() % 75 + 36, you should write rand() % 39 + 36 (A=36, B=75, B-A=39)

Doctirine 2 Case Statement

I use Doctirine 2 and zf2. How can i convert this sql query to dql. (Doctirine Query Language)
My product entity is here "Application\Entity\Product" I 've tried it but it doesn't work..
Thanks for your help.
SELECT price_range, count(*) AS num
FROM
(SELECT CASE WHEN price >= 0 AND price <= 10 THEN '0-10'
WHEN price >= 10 AND price <= 20 THEN '10-20'
WHEN price >= 20 AND price <= 30 THEN '30-40'
WHEN price >= 30 AND price <= 40 THEN '30-40'
WHEN price >= 40 AND price <= 50 THEN '40-50'
WHEN price >= 50 AND price <= 60 THEN '50-60'
WHEN price >= 60 AND price <= 70 THEN '60-70'
WHEN price >= 70 AND price <= 80 THEN '70-80'
WHEN price >= 80 AND price <= 90 THEN '90-100'
WHEN price >= 100 AND price <= 110 THEN '100-110'
ELSE 'over 1000'
END as price_range
FROM product
WHERE 1
) AS price_summaries
GROUP BY price_range
Well, unfortunately you can't. Doctrine doesn't support CASE. And looking at your problem, I'm also unable to find an adequate other solution with DQL.
You can however use a native query. Native queries are embedded raw SQL queries, basically an extension of PDO.
Native queries are of course generally discouraged, as they have two disadvantages:
You must do the hydration into Doctrine entities yourself, using ResultSetMapping (if you want the result of the query to contain ready-made entities instead of plain arrays/objects).
Native queries undermine the whole point of using a DBAL: you loose portability. (But, to be honest, most projects don't just switch their RDBMS, so it's a rather theoretical concern).
But if you need to have the above query executed, use a native query in this single case.
Doctirine support case statement.
This works
SELECT CASE WHEN (p.price >= 0 AND p.price <= 10) THEN '0-10'
WHEN (p.price >= 10 AND p.price <= 20) THEN '10-20'
WHEN (p.price >= 20 AND p.price <= 30) THEN '30-40'
WHEN (p.price >= 30 AND p.price <= 40) THEN '30-40'
WHEN (p.price >= 40 AND p.price <= 50) THEN '40-50'
WHEN (p.price >= 50 AND p.price <= 60) THEN '50-60'
WHEN (p.price >= 60 AND p.price <= 70) THEN '60-70'
WHEN (p.price >= 70 AND p.price <= 80) THEN '70-80'
WHEN (p.price >= 80 AND p.price <= 90) THEN '90-100'
WHEN (p.price >= 100 AND p.price <= 110) THEN '100-110'
ELSE 'over 1000'
END as price_range
FROM \Application\Entity\Product p
But this doesn't work, i think i should try native query
SELECT price_range, count(*) AS num
FROM
(SELECT CASE WHEN (p.price >= 0 AND p.price <= 10) THEN '0-10'
WHEN (p.price >= 10 AND p.price <= 20) THEN '10-20'
WHEN (p.price >= 20 AND p.price <= 30) THEN '30-40'
WHEN (p.price >= 30 AND p.price <= 40) THEN '30-40'
WHEN (p.price >= 40 AND p.price <= 50) THEN '40-50'
WHEN (p.price >= 50 AND p.price <= 60) THEN '50-60'
WHEN (p.price >= 60 AND p.price <= 70) THEN '60-70'
WHEN (p.price >= 70 AND p.price <= 80) THEN '70-80'
WHEN (p.price >= 80 AND p.price <= 90) THEN '90-100'
WHEN (p.price >= 100 AND p.price <= 110) THEN '100-110'
ELSE 'over 1000'
END as price_range
FROM \Application\Entity\Product p
) AS price_summaries
GROUP BY price_range

Clamping to "easy" numbers

So I'm trying to make a graphing application, and I'm using Desmos as a base for that.
The thing I'm struggling with is the way Desmos handles the subdivisions of the axes. When you zoom in or out the scales are always on "easy" simple numbers like 5, 100, 1000 etc. So my question is: how does one go about simplifying their scale with any level of zoom?
BTW: Using C++
I was going to write a description of how to do this in general, but then I realize that the code may be easier than explaining.
Most important step: define precisely what you mean by "easy simple" numbers.
Example #1: 1, 2, 4, 8, 16, 32, 64, 128, ... , 1073741824, ...
These are powers of two. So, a straightforward ceil(log(x)/log(2.0)) will solve it.
Example #2: 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, ...
There is a mixture of powers of two, and some multiples of it. Let's take a closer look.
A subset of these can be described as powers of ten.
Changing the formula to ceil(log(x)/log(10.0)) will solve it.
For each power-of-ten, its multiples by 2.0 and 5.0 are also "easy simple numbers".
Inside each iteration, after checking the power-of-ten value, also check the two multiples. If it fits inside one of the multiple, that value can be returned as result.
Code
The following code is only meant to explain the concept. It is not efficient - an efficient version should have used logarithm to get the result in O(1) time.
#include <iostream>
#include <vector>
#include <limits>
#include <stdexcept>
#include <algorithm>
using namespace std;
double getNiceAxisLength(double value, double baseLength, double step, const std::vector<double>& subSteps)
{
typedef std::vector<double>::const_iterator VecDoubleIter;
if (value < 0.0)
{
throw std::invalid_argument("Error: value must be non-negative. Take absolute value if necessary.");
}
if (baseLength <= 0.0)
{
throw std::invalid_argument("Error: baseLength must be positive.");
}
if (step <= 1.0)
{
throw std::invalid_argument("Error: step must be strictly greater than 1.");
}
for (VecDoubleIter iter = subSteps.begin(); iter != subSteps.end(); ++iter)
{
double subStep = *iter;
if (subStep <= 1.0 || subStep >= step)
{
throw std::invalid_argument("Error: each subStep must be strictly greater than 1, and strictly smaller than step.");
}
}
// make ascending.
std::vector<double> sortedSubSteps(subSteps.begin(), subSteps.end());
std::sort(sortedSubSteps.begin(), sortedSubSteps.end());
if (value <= baseLength)
{
return baseLength;
}
double length = baseLength;
double terminateLength = numeric_limits<double>::max() / step;
while (length < terminateLength)
{
for (VecDoubleIter iter = sortedSubSteps.begin(); iter != sortedSubSteps.end(); ++iter)
{
double subStep = *iter;
if (value <= length * subStep)
{
return (length * subStep);
}
}
double nextLength = length * step;
if (value <= nextLength)
{
return nextLength;
}
length = nextLength;
}
return baseLength;
}
int main()
{
double baseLength = 1.0;
double step = 10.0;
std::vector<double> subSteps;
subSteps.push_back(2.5);
subSteps.push_back(5);
for (int k = 0; k < 1000; k += ((k >> 2) + 1))
{
double value = k;
double result = getNiceAxisLength(value, baseLength, step, subSteps);
cout << "k: " << value << " result: " << result << endl;
}
cout << "Hello world!" << endl;
return 0;
}
Output
k: 0 result: 1
k: 1 result: 1
k: 2 result: 2.5
k: 3 result: 5
k: 4 result: 5
k: 6 result: 10
k: 8 result: 10
k: 11 result: 25
k: 14 result: 25
k: 18 result: 25
k: 23 result: 25
k: 29 result: 50
k: 37 result: 50
k: 47 result: 50
k: 59 result: 100
k: 74 result: 100
k: 93 result: 100
k: 117 result: 250
k: 147 result: 250
k: 184 result: 250
k: 231 result: 250
k: 289 result: 500
k: 362 result: 500
k: 453 result: 500
k: 567 result: 1000
k: 709 result: 1000
k: 887 result: 1000
Hello world!
Hello world!