Transform double to int multiple of 10 - c++

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.

Related

How does Cpp work with large numbers in calculations?

I have a code that tries to solve an integral of a function in a given interval numerically, using the method of Trapezoidal Rule (see the formula in Trapezoid method ), now, for the function sin(x) in the interval [-pi/2.0,pi/2.0], the integral is waited to be zero.
In this case, I take the number of partitions 'n' equal to 4. The problem is that when I have pi with 20 decimal places it is zero, with 14 decimal places it is 8.72e^(-17), then with 11 decimal places, it is zero, with 8 decimal places it is 8.72e^(-17), with 3 decimal places it is zero. I mean, the integral is zero or a number near zero for different approximations of pi, but it doesn't have a clear trend.
I would appreciate your help in understanding why this happens. (I did run it in Dev-C++).
#include <iostream>
#include <math.h>
using namespace std;
#define pi 3.14159265358979323846
//Pi: 3.14159265358979323846
double func(double x){
return sin(x);
}
int main() {
double x0 = -pi/2.0, xf = pi/2.0;
int n = 4;
double delta_x = (xf-x0)/(n*1.0);
double sum = (func(x0)+func(xf))/2.0;
double integral;
for (int k = 1; k<n; k++){
// cout<<"func: "<<func(x0+(k*delta_x))<<" "<<"last sum: "<<sum<<endl;
sum = sum + func(x0+(k*delta_x));
// cout<<"func + last sum= "<<sum<<endl;
}
integral = delta_x*sum;
cout<<"The value for the integral is: "<<integral<<endl;
return 0;
}
OP is integrating y=sin(x) from -a to +a. The various tests use different values of a, all near pi/2.
The approach uses a linear summation of values near -1.0, down to 0 and then up to near 1.0.
This summation is sensitive to calculation error with the last terms as the final math sum is expected to be 0.0. Since the start/end a varies, the error varies.
A more stable result would be had adding the extreme f = sin(f(k)) values first. e.g. sum += sin(f(k=1)), then sum += sin(f(k=3)), then sum += sin(f(k=2)) rather than k=1,2,3. In particular the formation of term x=f(k=3) is likely a bit off from the negative of its x=f(k=1) earlier term, further compounding the issue.
Welcome to the world or numerical analysis.
Problem exists if code used all float or all long double, just different degrees.
Problem is not due to using an inexact value of pi (Exact value is impossible with FP as pi is irrational and all finite FP are rational).
Much is due to the formation of x. Could try the below to form the x symmetrically about 0.0. Compare exactly x generated this way to x the original way.
x = (x0-x1)/2 + ((k - n/2)*delta_x)
Print out the exact values computed for deeper understanding.
printf("x:%a y:%a\n", x0+(k*delta_x), func(x0+(k*delta_x)));

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)

C++ Weird Variable Issues

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;

Double in object method not accepting fractional values?

I am having trouble with a C++ object-orientated script. When I create an object, I wish to calculate an AttributeQ based on its attributes MyAValue, MyBValue, and MyCValue.
While using the Visual 2010 debugger, I noticed that TempAttribueQ seems to always be 0 (except before it is initialized of course). Assuming Delta != 0, BVal == Maximum, and DeltaA == DeltaC, then TempAttribueQ should be 1/3 not 0.
At first I thought it was a scope problem, but the variable is defined outside the if-else statements. I have tried initializing TempAttribueQ as some outrageous number, which it keeps up until the if-else statements when it becomes 0 when it shouldn't.
This is my code...
void SetMyAttribueQ(){
double TempAVal = MyAValue;
double TempBVal = MyBValue;
double TempCVal = MyCValue;
double Minimum = min(min(TempAVal, TempBVal), TempCVal);
double Maximum = max(max(TempAVal, TempBVal), TempCVal);
double Delta = Maximum - Minimum;
double DeltaA = 0;
double DeltaB = 0;
double DeltaC = 0;
double TempAttribueQ = 0;
if(Delta == 0) {
MyAttribueQ = TempAttribueQ; // this->SetMyAttribueQ(TempAttribueQ);
}
else {
DeltaA = /* (a removed equation goes here... */
DeltaB = /* (a removed equation goes here... */
DeltaC = /* (a removed equation goes here... */
if(AVal == Maximum)
TempAttribueQ = (DeltaC - DeltaB);
else if(BVal == Maximum)
TempAttribueQ = (1/3) + (DeltaA - DeltaC);
else
TempAttribueQ = (2/3) + (DeltaB - DeltaA);
MyAttribueQ = TempAttribueQ;
}
}
What is preventing TempAttribueQ from getting a value of 1/3 or 2/3? Or, what is causing it to be set to be set to 0?
When you divide one integer by another, you get an integer result. Change either or both the constants to non-integer to fix it - C++ rules will result in the other being converted to floating point before the division takes place. All of the following will work:
1.0 / 3.0
1 / 3.0
1.0 / 3
An integer will get converted back to a double invisibly, which is why you weren't seeing any errors in your code.
1 is an integer and 3 is an integer so 1/3 uses integer arithmetic.
You want to use 1.0/3.0 to force double precision arithmetic.
1/3 == 0 due to integer division, which is set to TempAttribueQ.
You need to do 1./3 which will produce 0.3333333..
Try 1.0/3.0 and 2.0/3.0. 1/3 and 2/3 are 0 due to integer division.

sqrt(1.0 - pow(1.0,2)) returns -nan [duplicate]

This question already has answers here:
Why does floating-point arithmetic not give exact results when adding decimal fractions?
(31 answers)
Why pow(10,5) = 9,999 in C++
(8 answers)
Closed 4 years ago.
I've found an interesting floating point problem. I have to calculate several square roots in my code, and the expression is like this:
sqrt(1.0 - pow(pos,2))
where pos goes from -1.0 to 1.0 in a loop. The -1.0 is fine for pow, but when pos=1.0, I get an -nan. Doing some tests, using gcc 4.4.5 and icc 12.0, the output of
1.0 - pow(pos,2) = -1.33226763e-15
and
1.0 - pow(1.0,2) = 0
or
poss = 1.0
1.0 - pow(poss,2) = 0
Where clearly the first one is going to give problems, being negative. Anyone knows why pow is returning a number smaller than 0? The full offending code is below:
int main() {
double n_max = 10;
double a = -1.0;
double b = 1.0;
int divisions = int(5 * n_max);
assert (!(b == a));
double interval = b - a;
double delta_theta = interval / divisions;
double delta_thetaover2 = delta_theta / 2.0;
double pos = a;
//for (int i = 0; i < divisions - 1; i++) {
for (int i = 0; i < divisions+1; i++) {
cout<<sqrt(1.0 - pow(pos, 2)) <<setw(20)<<pos<<endl;
if(isnan(sqrt(1.0 - pow(pos, 2)))){
cout<<"Danger Will Robinson!"<<endl;
cout<< sqrt(1.0 - pow(pos,2))<<endl;
cout<<"pos "<<setprecision(9)<<pos<<endl;
cout<<"pow(pos,2) "<<setprecision(9)<<pow(pos, 2)<<endl;
cout<<"delta_theta "<<delta_theta<<endl;
cout<<"1 - pow "<< 1.0 - pow(pos,2)<<endl;
double poss = 1.0;
cout<<"1- poss "<<1.0 - pow(poss,2)<<endl;
}
pos += delta_theta;
}
return 0;
}
When you keep incrementing pos in a loop, rounding errors accumulate and in your case the final value > 1.0. Instead of that, calculate pos by multiplication on each round to only get minimal amount of rounding error.
The problem is that floating point calculations are not exact, and that 1 - 1^2 may be giving small negative results, yielding an invalid sqrt computation.
Consider capping your result:
double x = 1. - pow(pos, 2.);
result = sqrt(x < 0 ? 0 : x);
or
result = sqrt(abs(x) < 1e-12 ? 0 : x);
setprecision(9) is going to cause rounding. Use a debugger to see what the value really is. Short of that, at least set the precision beyond the possible size of the type you're using.
You will almost always have rounding errors when calculating with doubles, because the double type has only 15 significant decimal digits (52 bits) and a lot of decimal numbers are not convertible to binary floating point numbers without rounding. The IEEE standard contains a lot of effort to keep those errors low, but by principle it cannot always succeed. For a thorough introduction see this document
In your case, you should calculate pos on each loop and round to 14 or less digits. That should give you a clean 0 for the sqrt.
You can calc pos inside the loop as
pos = round(a + interval * i / divisions, 14);
with round defined as
double round(double r, int digits)
{
double multiplier = pow(digits,10);
return floor(r*multiplier + 0.5)/multiplier;
}