C++ Weird Variable Issues - c++

I'm using the following code to calculate and display the final score for a math game in C++.
int score = (correctNumber / 3) * 100;
cout << score;
The variable "correctNumber" is always a value between 0 and 3. However, unless "correctNumber" = 3, then the variable "score" always equals "0". When "correctNumber" equals 3 then "score" equals 100.
Say "correctNumber" was equal to 2. Shouldn't "score" be 67 then? Is this some issue with int variable type being unable to calculate decimal points?

You are doing math as integer so 1 / 3 is 0.
Try:
int score = (100 * correctNumber) / 3
and if you want to round:
int score = (100 * correctNumber + 1) / 3

I'm assuming correctNumber is an int, based on what you described. What's happening is integer truncation. When you divide an int by an int, the result always rounds down:
1/3 = 0.3333 = 0 as an integer
2/3 = 0.6667 = 0 as an integer
3/3 = 1.0000 = 1 as an integer
The easy way to remedy this here is to multiply it first:
int score = correctNumber * 100 / 3;
However, this still leaves you with 66 for 2, not 67. A clear and simple way of dealing with that (and many other rounding situations, though the rounding style is unconfigurable) is std::round, included since C++11:
int score = std::round(currentNumber * 100. / 3);
In the example, the dot in 100. makes 100 a double (it's the same thing as 100.0), so the result of the operation will be the floating-point value you want, not a pre-truncated value passed in as a floating-point value. That means you'll end up with 66.66666... going into std::round instead of 66.

Your guess is correct. int can't store real numbers.
But you can multiply first, and then divide, like
score = correctNumber * 100 / 3;
score will have 0, 33, 66, 100, depending on values of correctNumber

The problem is that (correctNumber / 3) is an integer, so you can't get 0.666 or any fraction to multiply by 100, which what I believe is you want.
You could try to force it to be a float like this:
int score = ((float)correctNumber / 3) * 100;
This, however, will give you 66 instead of 67, cause it doesn't round up. You could use C99 round() for that.
int score = round(((float)correctNumber / 3) * 100);
UPDATE:
You can also use + 0.5 to round, like this:
int score = (correctNumber / 3.0f) * 100.0f + 0.5f;

Related

Random number generation Function explanation

Can anyone explain these two lines of function??
int getRandomNumber(int min, int max)
{
static const double fraction = 1.0 / (RAND_MAX + 1.0);
return min + static_cast<int>((max - min + 1) * (rand() * fraction));
}
Looks like it's constraining rand() function's output to fall inside a min and max.
a double type value fraction is calculated from 1.0 / (RAND_MAX + 1.0);
RAND_MAX is a pre-compiler value defined in cstdlib or other header file or library, it's a big positive integer that represents the largest signed int your program can use. A higher RAND_MAX will make fraction lower since 1/number is a reciprocal; the reciprocal of 4 is 1/4 or 0.25. 5 is 1/5 or 0.20
The 1.0's are to implicitly cast RAND_MAX into a floating point number aka decimal; this makes sure that the / division / operator doesn't do integer division (5 / 2 == 2; vs 5.0 / 2.0 == 2.5)
return min + static_cast<int>((max - min + 1) * (rand() * fraction));
Return the integer representation of the min/max spread reduced by a random factor, added to the original minimum.
This line uses the min parameter value as a 'floor'. static_cast<int>() rounds down the floating point value of ((max - min + 1) * (rand() * fraction)) into an integer aka a whole number with no decimal parts. This cast is important for returning an int, but it also ensures that max is not exceeded by rounding down.
(max - min + 1) is the spread between the max and min parameters + 1. So if max == min you would be multiplying (rand() * fraction) by 1 instead of zero.
rand() generates a semi-random integer (no decimal parts) between 0 and RAND_MAX
Since fraction is the reciprocal of RAND_MAX + 1, fraction will always be < 1, and rand()s output will be a random portion of the min/max spread. The key part of understanding this function beyond the mixed C and C++ code confusion is knowing that RAND_MAX is used by the fraction variable AND the rand() function.
Think of the (rand() * fraction) part as a portion of distance from min
I would try feeding this function multiple values, tweaking the min, max, and fraction values each time and see how the output changes, you could probably find a pattern.
By making fraction smaller than (1.0 / RAND_MAX + 1.0) you can cluster the return values closer to the minimum.
(look up math ceiling and floor, and walnut's comment about uniform distribution). This can be done to smooth output, or make something more predictable, or cluster return values around an input value. If the math is the confusing part for you then messing around with code and seeing what happens will likely help your understanding and intuition of math functions.
Welcome to Stack Overflow!

How do you properly "snap" to a value?

Let say I've set a step of 0.1 in my application.
So, whatever fp value I get, I just need 1 digit after the comma.
So, 47.93434 must be 47.9 (or at least, the nearest fp representable value).
If I write this:
double value = 47.9;
It correctly "snap" to the nearest fp value it can get, which is:
47.89999999999999857891452847979962825775146484375 // fp value
101111.11100110011001100110011001100110011001100110011 // binary
Now, suppose "I don't write those values", but I got them from a software.
And than I need to snap it. I wrote this function:
inline double SnapValue(double value, double step) {
return round(value / step) * step;
}
But it returns these values:
47.900000000000005684341886080801486968994140625 // fp value
101111.11100110011001100110011001100110011001100110100 // binary
which is formally a little far than the first example (its the "next" fp value, 011 + 1).
How would you get the first value (which is "more correct") for each input value?
Here's the testing code.
NOTE: the step can be different - i.e. step = 0.25 need to snap value around the nearest 0.25 X. Example: a step of 0.25 will return values as 0, 0.25, 0.50, 0.75, 1.0, 1.25 and so on. Thus, given an input of 1.30, it need to wrap to the nearest snapped value - i.e. 1.25.
You could try to use rational values instead of floating point. The latter are often inaccurate already, so not really an ideal match for a step.
inline double snap(double original, int numerator, int denominator)
{
return round(original * denominator / numerator) * numerator / denominator;
}
Say you want steps of 0.4, then use 2 / 5:
snap(1.7435, 2, 5) = round(4.35875) * 2 / 5 = 4 * 2 / 5 = 1.6 (or what comes closest to it)

Transform double to int multiple of 10

I have a list of double being calculated from a formula. One of these double are for example 88.32547. I want to transform them into the nearest integer multiple of 10 and put them in another variable.
In the example double a = 88.32547 which lead to int b = 90 or if double a = -65.32547 leads to int b = -70.
10*std::round(x/10)
You may want to add an int cast :
int(10*std::round(x/10))
For details, see http://en.cppreference.com/w/cpp/numeric/math/round
Easiest way would be something like this
int a = (round(x / 10.0) * 10)
Divides by ten (to move the decimal point to the left), rounds off (to get to nearest integer) then multiplies by ten again.
In a situation where I could not use Round I used something like this (I needed something specific with negative integers) :
bottomValue = floor(a/10)*10;
topValue = ceil(a/10)*10;
if(a-bottomValue < topValue-a)
return bottomValue;
else
return topValue;
If you can use round :
roundValue = round(a/10)*10;
return roundValue;
Divide the number by 10, round to the nearest integer and multiply by 10 again.
Examples:
10 × round(88.32547 / 10) = 10 × round(8.832547) = 10 × 9 = 90
10 × round(−65.32547 / 10) = 10 × round(−6.532547) = 10 × −7 = −70
For rounding, you may consider using std::round.

Sum exceeding permissible value in looping floats

I recently created this simple program to find average velocity.
Average velocity = Δx / Δt
I chose x as a function of t as x = t^2
Therefore v = 2t
also, avg v = (x2 - x1) / (t2 - t1)
I chose the interval to be t = 1s to 4s. Implies x goes from 1 to 16
Therefore avg v = (16 - 1) / (4 - 1) = 5
Now the program :
#include <iostream>
using namespace std;
int main() {
float t = 1, v = 0, sum = 0, n = 0; // t = time, v = velocity, sum = Sigma v, n = Sigma 1
float avgv = 0;
while( t <= 4 ) {
v = 2*t;
sum += v;
t += 0.0001;
n++;
}
avgv = sum/n;
cout << "\n----> " << avgv << " <----\n";
return 0;
}
I used very small increments of time to calculate velocity at many moments. Now, if the increment of t is 0.001, The avg v calculated is 4.99998.
Now if i put increment of t as 0.0001, The avg v becomes 5.00007!
Further decreasing increment to 0.00001 yields avg v = 5.00001
Why is that so?
Thank you.
In base 2 0.0001 and 0.001 are periodic numbers, so they don't have an exact representation. One of them is being rounded up, the other one is rounded down, so when you sum lots of them you get different values.
This is the same thing that happens in decimal representation, if you choose the numbers to sum accordingly (assume each variable can hold 3 decimal digits).
Compare:
a = 1 / 3; // a becomes 0.333
b = a * 6; // b becomes 1.998
with:
a = 2 / 3; // a becomes 0.667
b = a * 3; // b becomes 2.001
both should (theoretically) result into 2 but because of rounding error they give different results
In the decimal system, since 10 is factorised into primes 2 and 5 only fractions whose denominator is divisible only by 2 and 5 can be represented with a finite number of decimal digits (all other fractions are periodic), in base 2 only fractions which have as denominator a power of 2 can be represented exactly. Try using 1.0/512.0 and 1.0/1024.0 as steps in your loop. Also, be careful because if you choose a step that is too small, you may not have enough digits to represent that in the float datatype (i.e., use doubles)

A small number is rounded to zero

I have the following values:
i->fitness = 160
sum_fitness = 826135
I do the operation:
i->roulette = (int)(((i->fitness / sum_fitness)*100000) + 0.5);
But i keep getting 0 in i->roulette.
I also tried to save i->fitness / sum_fitness in a double variable and only then applying the other operations, but also this gets a 0.
I'm thinking that's because 160/826135 is such a small number, then it rounds it down to 0.
How can i overcome this?
Thank you
edit:
Thanks everyone, i eventually did this:
double temp = (double)(i->fitness);
i->roulette = (int)(((temp / sum_fitness)*100000) + 0.5);
And it worked.
All the answers are similar so it's hard to choose one.
You line
i->roulette = (int)(((i->fitness / sum_fitness)*100000) + 0.5);
is casting the value to int which is why any float operation is truncated
try
i->roulette = (((i->fitness / sum_fitness)*100000) + 0.5);
and make sure that either 'sum_fitness' or 'i->fitness' is of of a float or double type to make the division a floating point division -- if they are not you will need to cast one of them before dividing, like this
i->roulette = (((i->fitness / (double)sum_fitness)*100000) + 0.5);
If you want to make this as a integer calculation you could also try to change the order of the division and multiplication, like
i->roulette = ( i->fitness *100000) / sum_fitness;
which would work as long as you don't get any integer overflow, which in your case would occur only if fitness risk to be above 2000000.
I'm thinking that's because 160/826135 is such a small number, then it rounds it down to 0.
It is integer division, and it is truncated to the integral part. So yes, it is 0, but there is no rounding. 99/100 would also be 0.
You could fix it like by casting the numerator or the denominator to double:
i->roulette = ((i->fitness / static_cast<double>(sum_fitness))*100000) + 0.5;