Arduino double subtraction returning 0 erronously - c++

I have a function that takes as parameter some double and does a subtraction operation on it. However I'm getting a result of 0 when one of the parameter is 0 for some reason.
int calcPID(double current, double desired, double k){
double diff;
diff = desired - current;
Serial.print("desired = ");
Serial.print(desired);
Serial.print(" ,current = ");
Serial.print(current);
Serial.print(",diff = ");
Serial.println(diff);
int r = (int)diff;
return r;
}
output
desired = 250.00 ,current = 1.69,diff = 248.31
desired = 250.00 ,current = 0.00,diff = 0.00
When the current is 0.00 the result(diff) is also 0.00 when it should be 250. Can someone tell me what's going on?
edit:
found out that I was getting a garbage value for current somehow that's not a double (I wrote 2 if conditions if current > 1 and if current <= 1 and neither of them were true).

This is very strange indeed.
I would suggest to create a second, minimal function like this:
int calcPID2(double current, double desired){
Serial.println(desired - current);
return(1);
}
and then gradually changing it to your original version, and see where it goes wrong (if it goes wrong..).
I have had some strange things with the Arduino software too in the past. Maybe you should check if you have the latest version.
You might also want to check if there is no memory or stack problem (i.e. if you have enough free memory left).

I think it's something with the floating point calculation. Have a look at this: https://www.arduino.cc/en/Reference/Float or google it and you will find pretty good answers :)

Related

Having trouble with decimal float in struct array [duplicate]

This question already has answers here:
Why does division result in zero instead of a decimal?
(5 answers)
Closed 1 year ago.
I am having some trouble and I cant really even figure out what is wrong, so I needed some help.
I need to take a percentage of a number that one of the structs in my array has, for each one.
my struct looks like
struct person{
int number;
string name;
float share;
}
So I use a for loop to get the total of number, no problem, all comes out good. But when I try to get what percent of the total I always get a zero.
for (int i=0; i<numberOfPersons;i++){
people[i].share = 100 * ((people[i].number)/totalNumber);
}
I don't understand what is going wrong here but people[i].share always comes out as 0.00 when I cout it.
literally all I do after this is cout it and I get the correct values from number and totalNumber. So I'm like really confused.
If I flip the division problem around I get answers(not the right ones obviously), so I know that there is data in the fields when the for loop runs. But where is it going when I run the equation the way I need to run it?
I tried initializing it and leaving uninitialized, swapping the pointers for ints made inside the loop, and more and I always get the same result.
Please help me understand.
I presume your type of totalnumber is int and person.number is int as well.
For operation between ints, the return value is still int
Expanding people[i].share = 100 * ((people[i].number)/totalNumber);
It would be something like people[i].share = 100 * ( 1/10 );
=> people[i].share = 100 * ( 0 );
=> people[i].share = 0;
So you will get 0 as a result;
To prevent it, cast one of int to float.
people[i].share = 100 * ((static_cast<float>(people[i].number))/totalNumber);

Recursion for evaluating log(1+x) using taylor series of the same

#include<iostream>
using namespace std;
double log(double x,int n)
{
static double p = x ;
double s;
if(n==1)
return x;
else
{
s=log(x,n-1);
p*=x;
if(n%2==0)
return s - (p/n);
else
return s + (p/n);
}
}
int main()
{
double r = log(1,15);
cout << r;
return 0;
}
I tried writing the above function for evaluating the log(1+x) function using its taylor series with recursion. But it didn't gave the result as I expected.
Eg :
ln(2) = 0.693 whereas my code gave 0.725. In the above code, n represents the number of terms.
Also I am new to this platform, so can I say that the above question is complete or does it need some additional information for further explanation?
There is nothing wrong with that piece of code: this has obviously got to do with the rate of convergence of the Taylor series.
If you take n = 200 instead of n = 15 in your code, the approximation error will be low enough that the first two decimals of the exact solution ln(2) = 0.693147... will be the correct ones.
The more you increase the n parameter, the better approximation you will get of ln(2).
Your program does converge to the right number, just very slowly...
log(1,15) returns 0.725, as you noticed, log(1,50) is 0.683, log(1,100) is 0.688, and log(1,200) is 0.691. That's getting close to the number you expected, but still a long way to go...
So there is no C++ or recursion bug in your code - you just need to find a better Taylor series to calculate log(X). Don't look for a Taylor series for log(1+x) - these will typically assume x is small, and converge quickly for small x, not for x=1.

Why do these functions give the correct output 75% of the time?

(this function is part of a larger program but operates independently of other functions.)
Ok I have a function jacket and given 3 inputs it produces the correct output only 75% of the time.
I do not know the inputs but I know the output is wrong.
I do not know what is wrong and have no idea how to fix it.
I assume it is the same 12 values entered each time the function is submitted to myProgrammingLab.
So it may be a problem with a specific input.
Thanks.
The Description:
Jacket size (chest in inches) = height times weight divided by 288 and then adjusted by adding 1/8 of an inch for each 10 years over age 30. (note that the adjustment only takes place after a full 10 years. So, there is no adjustment for ages 30 through 39, but 1/8 of an inch is added for age 40.)
edit: changing tmp to float still produced the error.
float jacket(float weight, float height, int age) {
double result = (height * weight) / 288;
/*now for every 10 years past 30 add (1/8) to the result*/
if((age - 30) > 0){
int temp = (age - 30) / 10;
result = result + (temp * .125);
}
return result;
}
This is the same function written differently with the same problem.
float jacket(double jWeight, double jHeight, int jAge)
{
double jSize = ((jWeight*jHeight)/288.0);
int i = jAge/10 - 3;
if((jAge/10)>3)
jSize += 0.125*i;
return jSize;
}
This is a third function with the same problem
float jacket(double weight, double height, int age)
// calculates the jacket size, adjusting for age in increments
// of ten years, if customer is over 30 years of age.
{
int age_factor;
double j_size;
j_size = (height*weight)/288.0;
if (age >=30)
{
age_factor = (age-30)/10; //note possible truncation.
j_size += age_factor/8.0;
}
return j_size;
}
The first time the function is called it produces an incorrect return value. the remain 3 times it is called the return value is correct.
Observe:
Expected Output:
jacket·size·=·24.17↵
jacket·size·=·40.00↵
jacket·size·=·46.04↵
jacket·size·=·35.42↵
Actual Output:
jacket·size·=·24.29↵
jacket·size·=·40.00↵
jacket·size·=·46.04↵
jacket·size·=·35.42↵
*All three functions given the same input produce the same output
int temp = (age - 30) / 10;
By making temp an int, you will get incorrect results, because of truncation. Try using a float instead.
I guess one could say that 31 isn't necessarily 1 year over 30. Try int temp = (age - 31)/10;. Personally I think that's wrong, as does everyone else here, but someone could argue that the moment one turns 31 one is only a few seconds over 30. It's worth a try, anyway.

SPOJ SCUBADIV - Recursive DP Approach [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I have been trying to solve http://www.spoj.com/problems/SCUBADIV/ question at SPOJ. I have come up with a recursive DP solution.
I am using knapsack approach with a 3 dimensional array to store the number of cylinders, required oxygen weight, and nitrogen weight. At each recursive step I'm checking for the amount of oxygen and nitrogen yet to be filled. If it is negative, it's as good as zero.
#include<bits/stdc++.h>
using namespace std;
#define inf 99999999
int n;
vector<int> o;
vector<int> ni;
vector<int> w;
int ow;
int nw;
int knapsack(int n,int ow,int nw); // n - number of cylinders,ow-wt. of oxygen
// nw-wt. of nitogen.
int main(){
int t;
scanf("%d",&t);
while(t--){
int i;
scanf("%d %d",&ow,&nw);
scanf("%d",&n);
o.resize(n);
ni.resize(n);
w.resize(n);
for(i=0;i<n;i++)
scanf("%d%d%d",&o[i],&ni[i],&w[i]); // o[i] storing wt. of oxygen cylinders
int res = knapsack(n,ow,nw); //ni[i] storing wt. of nitrogen cylinders
printf("%d",res);
}
return 0;
}
int knapsack(int n,int ow,int nw){
int dp[n+1][ow+1][nw+1];
memset(dp,inf,sizeof (dp)); //setting value of array to inf to get minimum weight
int i;
for(i=0;i<n;i++)
dp[i][0][0]=0;
if(dp[n][ow][nw]!= inf)
return dp[n][ow][nw];
else if (ow - o[n-1]>=0 && nw - ni[n-1]>=0)
return dp[n][ow][nw]= min(knapsack(n-1,ow,nw),w[n-1]+knapsack(n-1,ow-o[n-1],nw-ni[n-1]));
else if(ow -o[n-1]<0 && nw - ni[n-1] >=0)
return dp[n][ow][nw]=min(knapsack(n-1,0,nw),w[n-1]+knapsack(n-1,0,nw-ni[n-1]));
else if(ow-o[n-1]>=0 && nw-ni[n-1]<0)
return dp[n][ow][nw]=min(knapsack(n-1,ow,0),w[n-1]+knapsack(n-1,ow-o[n-1],0));
else if(ow-o[n-1]<0 && nw-ni[n-1]<0)
return dp[n][ow][nw]= knapsack(n-1,0,0);
}
This code is not giving the desired result (it's giving -1). Is the approach correct ?
There is a problem with this code:
int dp[n+1][ow+1][nw+1];
memset(dp,inf,sizeof (dp));
The memset() function sets a byte pattern, not a value. Since inf is a larger-than-a-byte value, it is essentially doing inf % 256 and initializing all the bytes in dp[][][] to that value. This is further complicated by dp[][][] being of base type int, so 4 bytes set to the same byte value is something unexpected.
In the case of your value for inf, of 99999999, the byte value will be 0xff, and so all the ints in dp[][][] will be set to -1.
I don't know if this is expected, but it looks like it could be a mistake.
Let M(x, O, N) be the minimum weight of cylinders that will provide O liters of oxygen and N liters of nitrogen by choosing from only cylinders 1 to x. Let O(x), N(x), and W(x) be the amount of oxygen and nitrogen available in the x'th cylinder and the cylinder's weight respectively. Then either we choose to use the x'th cylinder or we don't:
M(x, O, N) = min( W(x) + M(x - 1, O - O(x), N - N(x)), M(x - 1, O, N) )
The base case occurs when we have no cylinders at all.
M(0, O, N) = 0 if O <= 0 and N <= 0, infinity otherwise
I won't be reading your unformatted, cryptically written code to figure out whether it implements this correctly. I will say memset can only be used to set bytes to a given value. Your call is not doing what you think. Additionally, your recursive procedure returns junk if execution reaches the end of the if chain.
Work a small example by hand. Run your code either in a debugger or with printfs inserted to show what's going on. Figure out where its actual execution diverges from your hand calculation.
Yes, it is possible to solve this problem with a recursive approach, but this is not how to do it. There are multiple problems with the code, and 'obviously' it will return -1. The question is I shall try to answer is: tell me some of the things wrong with this code.
Variable names like dp obscure the meaning of the code. Give them meaningful names!
Don't resize a vector and read into a pointer. Read values and push them onto the vector.
Print out the data to ensure you read it right.
The memset function fills with bytes, in this case -1. Use a loop to initialise ints.
The first if statement can only ever return 0 or -1 (or inf once you fix the init). As it is the other code will not be executed.
Assigning a value into dp is of no effect, since it is in automatic storage (on the stack).
I don't understand the chain of if statements. Explain them.
There is no else so the function can fall off the end.
Best to rewrite, debug, and if it still doesn't work come back with something we can read.

Calculating the value of arctan(x) in C++

I have to calculate the value of arctan(x) . I have calculated the value of this by evaluating the following series :
Arctan (x) = x – x^3/3 + x^5/5 – x^7/7 + x^9/9 - …
But the following code can not calculate the actual value. For example, calculate_angle(1) returns 38.34 . Why?
const double DEGREES_PER_RADIAN = 57.296;
double calculate_angle(double x)
{
int power=5,count=3;
double term,result,prev_res;
prev_res = x;
result= x-pow(x,3)/3;
while(abs(result-prev_res)<1e-10)
{
term = pow(x,power)/power;
if(count%2==0)
term = term*(-1);
prev_res=result;
result=result+term;
++count;
power+=2;
// if(count=99)
// break;
}
return result*DEGREES_PER_RADIAN;
}
EDIT: I found the culprit. You forgot to include stdlib.h, where the function abs resides. You must have ignored the warning about abs being implicitly declared. I checked that removing the include yields the result 38.19 and including it yields the result ~45.
The compiler is not required to stop compilation when an undeclared function is being used (in this case abs). Instead, it is allowed to make assumptions on how the function is declared (in this case, wrong one.)
Besides, like other posters already stated, your use of abs is inappropriate as it returns an int, not a double or float. The condition in the while should be >1e-100 not <1e-100. The 1e-100 is also too small.
--
You forgot to increase count and power after calculating the first two summands:
prev_res = x;
result= x-pow(x,3)/3;
count = 4; <<<<<<
power = 5; <<<<<<
while(abs(result-prev_res)<1e-100)
{
term = pow(x,power)/power;
if(count%2==1)
term = term*(-1);
Also I consider your use of the count variable counterintuitive: it is intialized with 3 like if it denotes the last used power; but then, loop iterations increase it by 1 instead of 2 and you decide the sign by count%2 == 1 as opposed to power%4 == 3
The series converges to tan^{-1} x, but not very fast. Consider the series when x=1:
1 - 1/3 + 1/5 - 1/7 + 1/9 - ...
What is the error when truncating at the 1/9 term? It's around 1/9. To get 10^{-100} accuracy, you would need to have 10^{100} terms. The universe would end before you'd get that. And, catastrophic round-off error and truncation error would make the answer utterly unreliable. You only have 14 digits to play with for doubles.
Look at reference works like Abramowitz and Stegun [AMS 55] or the new NIST Digital Library of Mathematical Functions at http://dlmf.nist.gov to see how these are done in practice. Often, one uses Padé approximants instead of Taylor series. Even when you stick with Taylor series, you often use Chebyshev approximation to cut down on the total error.
I also recommend Numerical Methods that [Usually] Work, by Forman Acton. Or the Numerical Recipes in ... series.
Your sign is the wrong way around after the first two terms. It should be:
if(count%2==0)
term = term*(-1);
Your comparison is the wrong way around in the while condition. Also, you're expecting an unrealistically high level of precision. I would suggest something more like this:
while(fabs(result-prev_res)>1e-8)
Finally, you'll get a more accurate result with a better value for DEGREES_PER_RADIAN. Why not something like this:
const double DEGREES_PER_RADIAN = 180/M_PI;