C++ is rounding the result of my function - c++

I created a program with a function to convert numbers from a string to a numeric variable (the program will be copied below). I started off using a double; however, for some reason, whenever I built it, it kept rounding the last number up or down if I used decimals. I don't understand why so I would be grateful for any insight you guys could share with me.
#include <iostream>
using namespace std;
//variables initialised in a set of curly brackets are called local variables
//variables initialised outside a set of curly brackets are called global variables
// local variables can only be used in that set of curly brackets
// global variables can be used anywhere after it has been declared
// global variables are automatically set to 0 when it has not been assigned a value
//a void function is a function that returns nothing
//StringName.length() returns the length of a string
/*----------------------------------------FUNCTION-------------------------------------*/
int pow(int a, int b){
int c = 1;
for(int i=0;i<b;i++){
c*=a;
}
return c;
}
float StringNoToNo(string a){
float b=0.0;
int y = 1;
int s = 0;
//cout<<"a.length() is: "<<a.length()<<endl;
for(int i = (a.length()); i>0;i--){
// cout<<"the loop: "<<(a.length()-i)<<endl;
int z = a[i-1];
//cout<<"z = "<<z<<endl;
switch(z){
case 48 ... 57:
// cout<<"(a[i]>=48)&&(a[i]<=57) is true"<<endl;
//cout<<"pow(10.0,(a.length()-i)) = "<<pow(10.0,(a.length()-i))<<endl;
//cout<<"a.length() - i = "<<(a.length()- i)<<endl;
b += ((a[i-1]-48)* pow(10.0,(a.length()-i-s)));
// cout<<"b= "<<b<<endl;
break;
case 46:
y=pow(10,(a.length()-i));
// cout<<"y = "<<y<<endl;
if(s==0){
s++;}else{
goto v;
}
break;
default:
v:
// cout<<"(a[i]<48)||(a[i]>57) is true"<<endl;
cout<< "the number was not written properly"<<endl;
return 0;
break;
}
}
//cout<<" b = "<<b<<endl;
//cout<<"b/y = "<<b/y<<endl;
return (b/y);
}
/*----------------------------------------FUNCTION-------------------------------------*/
// overloading functions - you can create multiple functions with the same name so as long
// as they have different parameters.
// as long as the function is declared at the beginning, even if the function meant to
// overload it is written at the end of the code, it can still be used.
main() {
string no;
cout << "write a number: ";
cin >> no;
cout << "the number is: "<<StringNoToNo(no)<<endl;
}
At first, I used the double variable for the function and then changed it to float. After that, I used cout at various parts of the loop to see what was going on at every step of the way but still couldn't understand the problem.
The input and output I get are:
write a number: 1234.6789
the number is: 1234.68
Process returned 0 (0x0) execution time : 4.713 s
Press any key to continue.
Of course, if I remove the // from the cout functions:
write a number: 1234.6789
the number is: a.length() is: 9
the loop: 0
z = 57
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 1
a.length() - i = 0
b= 9
the loop: 1
z = 56
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 10
a.length() - i = 1
b= 89
the loop: 2
z = 55
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 100
a.length() - i = 2
b= 789
the loop: 3
z = 54
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 1000
a.length() - i = 3
b= 6789
the loop: 4
z = 46
the loop: 5
z = 52
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 100000
a.length() - i = 5
b= 46789
the loop: 6
z = 51
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 1000000
a.length() - i = 6
b= 346789
the loop: 7
z = 50
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 10000000
a.length() - i = 7
b= 2.34679e+06
the loop: 8
z = 49
(a[i]>=48)&&(a[i]<=57) is true
pow(10.0,(a.length()-i)) = 100000000
a.length() - i = 8
b= 1.23468e+07
1234.68
Process returned 0 (0x0) execution time : 24.055 s
Press any key to continue.

b= 1.23468e+07 proves that your function isn't rounding, it's returning the correct value.
It's actually cout << that's doing the rounding. Use cout << precision(8) to make it display 8 digits of precision instead of the default of 6 digits.

Related

Converting MQL4 to C++?

I would like to convert a bunch of stock/forex indicators written in MQL4 (.mq4 files) to C++. Previously, I had only been programming in Python and had very little exposure to both MQL4 and C++. Furthermore, I am not at all aware of the ways to go about such a problem, and whether it is even feasible. (Although, worst case scenario, manually recoding them all should definitely be feasible.)
I took a simple indicator, the Simple Moving Average, as an example and started tinkering with it and running it using a C++ compiler. Knowing that the syntax of the two languages is highly similar, I thought this could be a relatively easy process, and even automable to some degree.
Here is the Simple Moving Average script extracted from the .mq4 file available at this link:
MA_Period=5;
void sma()
{
double sum=0;
int i,pos=Bars-ExtCountedBars-1;
//---- initial accumulation
if(pos<MA_Period) pos=MA_Period;
for(i=1;i<MA_Period;i++,pos--)
sum+=Close[pos];
//---- main calculation loop
while(pos>=0)
{
sum+=Close[pos];
ExtMapBuffer[pos]=sum/MA_Period;
sum-=Close[pos+MA_Period-1];
pos--;
}
//---- zero initial bars
if(ExtCountedBars<1)
for(i=1;i<MA_Period;i++) ExtMapBuffer[Bars-i]=0;
}
And here is my C++ implementation, at the moment testing it on a short array arr[] representing the Close array in MQL4. Furthermore, I dropped MQL4's Bars and ExtCountedBars variables (as I want to run the indicator on static, historical data), and replaced ExtMapBuffer with an array called output[], with equal length as the "price" array arr[].
#include <iostream>
using namespace std;
int main()
{
int MA_Period=5;
int arr[20] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
double sum=0;
int i, pos=0;
int output[20];
cout << "Pos: " << pos << endl;
//---- initial accumulation
if(pos<MA_Period) pos=MA_Period;
for(i=1;i<MA_Period;i++,pos--)
sum+=arr[pos];
cout << "Sum of past " << MA_Period << " prices : " << sum << endl;
cout << "Pos = " << pos << endl;
//---- main calculation loop
while(pos>=0)
{
sum+=arr[pos];
output[pos]=sum/MA_Period;
sum-=arr[pos+MA_Period-1];
pos--;
}
for(int j=0;j<sizeof(output)/sizeof(output[0]);j++){
cout << "output[" << j << "] = " << output[j] << endl;
}
return 0;
}
The console output I'm gettign for the output array values are:
output[0] = 3
output[1] = 4
output[2] = 65535
output[3] = 1
output[4] = 1706671568
output[5] = 32766
output[6] = 4197523
output[7] = 0
output[8] = 2
output[9] = 0
output[10] = 4197613
output[11] = 0
output[12] = 124
output[13] = 0
output[14] = 0
output[15] = 0
output[16] = 4197536
output[17] = 0
output[18] = 4196352
output[19] = 0
which is clearly not correct. I tried retaining as much from the original MQL4 code when converting to C++ but now hit a roadblock as to why the output is massively different from the expected:
output[0] = nan
output[1] = nan
output[2] = nan
output[3] = nan
output[4] = 3
output[5] = 4
output[6] = 5
output[7] = 6
output[8] = 7
output[9] = 8
output[10] = 9
output[11] = 10
output[12] = 11
output[13] = 12
output[14] = 13
output[15] = 14
output[16] = 15
output[17] = 16
output[18] = 17
output[19] = 18
What am I missing / misunderstanding in the process of converting my MQL4 code to C++?
There are several problems with this code. The main issue is your use of indices i and pos. In particular, after the initial accumulation, pos is equal to 1, so the main calculation loop will only run one iteration before it is done. So only output[1] gets written to, the rest of the array is uninitialized, and may contain any value.
Also note that array indices in C start at zero. Your initial accumulation loop starts at 1, which is not what you want.
I would avoid having two variables for indices, and only use one. To initialize sum, write:
for (int i = 0; i < MA_Period; ++i) {
sum += arr[i];
output[i] = -1;
}
Then to do the remainder write:
for (int i = MA_Period; i < sizeof(output) / sizeof(output[0]); ++i) {
sum += arr[i];
sum -= arr[i - MA_Period];
output[i] = sum / MA_Period;
}
This will give you the expected output. Note that there is no way to get nan for the first 5 values, as an int can never be nan. If you make output an array of double it is possible though, for example using this line in the initial loop:
output[i] = 0.0 / 0.0;
As for why the original MQL4 code worked: it initializes pos to Bars - ExtCountedBars - 1, whereas you initialized it to 0 in your C++ version.

Why 54 + 400 = 453?

I wanted to convert a string to an integer, and I find the "454" was converted to 453.
I have defined a function which can convert an integer-string to an integer. But when I tested it, I found the "454" was converted to 453. I tried another number 565, and it is correct.
#include <iostream>
#include <string>
#include <math.h>
using namespace std;
int strtonum(string num){
int i = 0;
int n = 0;
int result=0;
for(i = num.length()-1; i>=0; i--,n++){
if(num[i] == '-'){
result-=2*result;
break;
}
cout<<result<<" + "<<(num[i] - '0')*pow(10,n);
result += (num[i] - '0')*pow(10,n);
cout<<" = "<<result<<endl;
}
return result;
}
int main()
{
string x;
cin>>x;
cout<<strtonum(x)<<endl;
return 0;
}
Result
454
0 + 4 = 4
4 + 50 = 54
54 + 400 = 453
453
Process returned 0 (0x0) execution time : 2.763 s
Press any key to continue.
565
0 + 5 = 5
5 + 60 = 65
65 + 500 = 565
565
Process returned 0 (0x0) execution time : 3.314 s
Press any key to continue.
Your approach involves floating-point computations through your use of the std::pow function.
As you may know, floating-point computations can introduce error. I'm a little surprised to see that here with good wholesome whole numbers, but still you're not dealing with it at all before truncating back to int.
I suggest a different, integer-only manner of raising to a power of ten (perhaps a nice loop!).
Also, as bruno pointed out, this:
result-=2*result;
is overflow-prone and unnecessary when you can just do this instead:
result = -result;
or:
result *= -1;
The usual approach to this is to accumulate values with multiplication by 10:
int convert(std::string text) {
bool negative = false;
int cur = 0;
if (text[cur] == '-') {
negative = true;
++cur;
}
int value = 0;
while (cur < text.length()) {
value *= 10;
value += text[cur++] - '0';
}
if (negative)
value = -value;
return value;
}
Note: this code has not been tested. It might contain errors.

Why is 1 * 4 = 196?

Im trying to make a binary converter, the problem however is that when I build it, it usually decrypts my test number "101" which should be 5 into something along the lines of 300 - 3000.
int main()
{
char a;
string bintered;
int bincrypted = 0, bincrypter;
cout<<"Would you like to try the binary to decimal converter? Y/N"<<endl;
cin>>a;
if (a == 'Y' || a == 'y')
{
cout<<"Ok, enter a binary number and we will decrypt it > ";
cin>>bintered;
int x = bintered.length() - 1; //multiplier counting down
int y = 0;
int power = 0;
while (x != -1)
{
power = bintered[y] * pow(2.0, x);
bincrypted = bincrypted + power;
y++;
x = x - 1;
}
cout<<"Final answer is: "<<bincrypted<<endl;
}
return 0;
}
When I tried doing cout<<bintered[y] * pow(2.0, x); it gave me 196, 96 and 49 for the three loops it did.
Am i using the pow function incorrectly or what?
bintered[y] returns the ascii code of the character, so 48 for 0 and 49 for 1.

Project Euler 8 in c++

I'm trying to solve problem 8 from project euler but I'm getting way too big numbers as results and I don't know why.
The problem is "Find the thirteen adjacent digits in the 1000-digit number that have the greatest product. What is the value of this product?"
My code :
#include <iostream>
#include <string>
int main()
{
std::string str = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450";
long long a = 1;
long long fin = 0;
for (int c = 0; c < 988; c++)
{
for (int d = 0; d < 13; d++)
{
a = a * str.at(c + d);
}
if (a > fin)
{
fin = a;
std::cout << fin << " at " << c << std::endl;
}
a = 1;
}
system("pause");
}
The output :
7948587103611909356 at 0
8818137127266647872 at 15
8977826317031653376 at 71
9191378290313403392 at 214
9205903071867879424 at 573
Press any key to continue...
The problem is that the characters '0' through '9' are not the same as the integers 0 through 9; rather, '0' has the value 48, '1' has the value 49, and so on. (These are the ASCII values of those characters.)
So to convert from a digit character to the desired number — for example, to extract e.g. 3 from '3' — you need to subtract '0'. In other words, you need to change this:
a = a * str.at(c + d);
to this:
a = a * (str.at(c + d) - '0');

C/C++. input line of numbers

Need to input data about multiple structure variables (format - 3 groups of 2 numbers in one line). Used "for" and custom input function (also it calculates some parameters). Now tryed to use "std::cin" :
typedef struct {
short width;
short height;
short left;
short top;
int S;
short orientation;
} Rectangle;
bool input_rectangle(Rectangle* rect) {
short width;
short height;
std::cin >> width >> height;
(*rect).width = width;
(*rect).height = height;
(*rect).S = width * height;
(*rect).top = 0;
(*rect).left = 0;
if(width>height) {
(*rect).orientation = HORIZONTAL;
}
else {
(*rect).orientation = VERTICAL;
}
return width!=0 || height!=0;
}
int main() {
Rectangle* rectangles = new Rectangle[RECTANGLES_COUNT];
...
while(1) {
...
for(int i=0;i<RECTANGLES_COUNT;i++) {
will_continue = will_continue || input_rectangle(&rectangles[i]);
}
if(!will_continue) {
break;
}
else {
int S = calculate(rectangles);
}
...
}
}
It give wrong result. Tryed to add debug output to "calculate" :
for(int i=0;i<RECTANGLES_COUNT;i++)
std::cout << rectangles[i].width << " x " << rectangles[i].height << " = " << rectangles[i].S << "\n";
Example of result.
4 16 6 6 5 10 #my input
4 x 16 = 64 #right
0 x 0 = 0 #??? Must be 6 x 6 = 36
0 x 0 = 0
646 x 6 = 36
0 x 0 = 0
0 x 0 = 0
365 x 10 = 50
0 x 0 = 0
0 x 0 = 0
How can I improve it? Also I tryed to use scanf("%hd %hd", &width, &height); (may ise pure C in this task), but it give same result.
Used g++ compiler / (gcc for pure C version)
From your debug output code, I'm gathering that for your test purposes RECTANGLES_COUNT is actually defined to 3.
Also, since it is able to perform any kind of computations, and given that the || operator is subject to lazy-evaluation, you must be initializing will_continue to false.
What's happening is when your first input (i=0) is in fact valid (i.e. width or height is not 0), will_continue gets set true. Then since true || anything must be true, input_rectangle is no longer called (lazy-evaluation) for i=1,2,... So only rectangle[0] gets set in that loop. When you latter call your debug output in calculate, you show all 3 rectangles' width/height/S including 2 that have presumably been initialized to 0 (and remain to their initial value).
I'm guessing (though not shown) that int S = calculate(rectangles) might in fact assigns the sum of rectangle[i].S (which happens to be equal to rectangle[0].S, since the others are 0s) to S which you are then printing. That would explain the lines containing 646 (64 followed by 6 x 6) and 365 (36 followed by 5 x 5).
I'm guessing what you wanted was probably more along the lines of:
...
while(1) {
...
bool will_continue = false;
for(int i=0;i<RECTANGLES_COUNT;i++) {
will_continue = input_rectangle(&rectangles[i]);
if (!will_continue) {
break;
}
}
if(!will_continue) {
break;
}
else {
int S = calculate(rectangles);
}
...
}
return width!=0 || height!=0;
should be
return width!=0 && height!=0;