a lot of decimal value storage in C++ - c++

I wanted to write a program that returns how many months we could survive when we're given
our monthly expenditure, amount of disposable income, and interest rate (all in integers).
For instance, if we start with disposable income = 1000, interest rate = 5%, monthly expenditure = 100, then
after first month: 1000*1.05 - 100 = 950, we have 950 dollars left
after second month: = 950*1.05 - 100 = 897.5
and so on, and in the end, we can survive 14 months.
I wrote the following code in C++:
int main(){
int i=0;
int initialValue;
int interest;
int monthly;
double value=1.0*initialValue;
double r=1+1.0*interest/100;
while(value > 0){
if(value < monthly){
break;
}
else
{
value=value*r-monthly;
i++;
}
};
cout<<i;
return 0;
}
but for sufficiently large values of initialValue and small values of monthly, the program I wrote runs very slowly to the degree that it's unusable. Is there a problem with the code that makes it run not well (or very slow)?
Any help would be greatly appreciated.

double cannot store numbers precisely. One consequence of this is when you subtract a very small number from a very large number, the result is not changed from the original large value.
One solution to this problem is to use an int to do your calculations. Think of the values as the number of pennies, rather than the number of dollars.

A few notes:
The *1.0's are pointless. Instead, take advantage of implicit and explicit casts:
double value=initialValue;
double r=1+(double)interest/100;
++i is faster than i++.
value=value* can be rewritten as value*=.
You can mix the first two conditionals. Remove the if...break and change the while loop to while (value > 0 && value < monthly).

On the face of it, the reason this runs slowly is the large number of iterations. However, you didn't specify any specific numbers and I would expect this code to be able to execute at least a million iterations per second on any reasonably fast processor. Did you really expect to need to calculate more than 1 million months?
Apart from the novice style of the code, the underlying problem is the algorithm. There are very simple formulae for making these calculations, which you can find here: https://en.wikipedia.org/wiki/Compound_interest. Your situation is akin to paying off a loan, where running out of money equals loan paid off.

Related

Same math and numbers different answers?

im writing a simple program that you give a number of days and it gives back the number of years weeks and days that equal to the numbers of days you give.
but i noticed that you can get two different answers even tho when i checked the math it makes sense in both cases .
can someone please please explain to me why the answers are different and which one is correct
#include<iostream>
using namespace std;
int main()
{
int y;
int d,w;
int Days;
cin>>d;
y=d/365;
int LessThanAYearDays = d%365;
Days=LessThanAYearDays%7;
w=LessThanAYearDays/7;
int SameDays = d%7;
cout<<"answer1 is : "<<y<<" "<<w<<" "<<Days<< "\n";
cout<<"answer2 is : "<<y<<" "<<w<<" "<<SameDays<< "\n";
return 0;
}
There are not an exact multiple of weeks in a year, so you are displaying different things. They will be the same in years divisible by 7.
E.g. Assume that a given year starts on a Tuesday.
Days corresponds to how many days past the last Tuesday you are.
SameDays corresponds to what day you are on.
See also the distinction that std makes between a std::chrono::duration, which is a count of time, and a std::chrono::time_point, which is a count of time since a particular date.

Computer guesses your number (has to be in 10 tries) from 1-1000

OK, to start off I am a complete beginner in a computer science class. I could ask my teacher, but I don't have time to do so. So, expect some really dumb errors that I can't see and I am using eclipse.
here's my code:
#include <iostream>
using namespace std;
int something()
{
int big = 1000;//largest number is 1000
int small = 1;//smallest number is 1
//so, best guess is to go in the middle
int c;//my guesses
int inequality;//used to write if statements
for (int a = 0; a <= 10; a++)
{
cout << "Think about a number between 1-1000" << endl;//what console tells you
c = (big - small) / 2;//my guess will be the midpoint of the two numbers
while (big > small)//while the highest number is ALWAYS greater than the lowest number
{
cout << "Is your number less than, equal to, or greater than my guess? 1-less,2-equal,3-greater" << c << endl;
cin >> inequality;//you tell me whether my guess is too high, low, or equal
if (inequality == 1)//if you say it is too low...
{
small = c;//the smallest number is now my last guess
c = c - (big - small) / 2;//so, I'll take the midpoint of the CURRENT biggest and smallest number
}
else if (inequality == 2)//if you say it is equal...
{
cout << "Yay, I guessed your number." << endl;//cool.
}
else if (inequality == 3)//if you say it is too high...
{
big = c;//biggest number is now my guess
c = c + (big - small) / 2;//so, I'll take the midpoint of the CURRENT biggest and smallest number
}
}
}
system("pause");
return 0;//returns something in int main function
}
int main()
{
something();//so I can actually do code.
}
So my problem:
If I enter 1 after the console enters the first guess, I get 499, which is fine. After the second guess (where I enter 1), I get 249, which is also fine. However, the third guess after I enter 1 gets a random 681, so could someone help me?
It would be most appreciated if you did not rewrite the entire code for me, otherwise that is really suspicious when I turn it in. I am struggling because I do not have very good computer science background, so to improve, I need ideas mostly. Lastly, any way to make my code look a LITTLE more professional would be appreciated :)
Also, my for loop may be a bit off, I'm not sure.
When you calculate next number you need to change range
So you have first
small guess big
+---------+----------+
if user says too small, then the answer is above the guess, so in the range
big - guess and that is what you need to cut in half so instead of
c = c - (big - small)/2
guess = (big - guess) / 2 + guess
if user says too big then the answer is between guess and small
guess = (guess - small) / 2 + small
Try removing the c+ and c - terms from your midpoint calculations.
Edit: Also, try swapping the small = c and big = c statements in the two conditionals.
Your comments are mostly incorrect and that was my source of confusion.

SIGSEGV Error on Dynamic Programming - CodeChef

Hope you all are having a great day!
I love programming, but these past days I am having sleepless nights, with CodeChef always returning SIGSEGV errors on my Dynamic Programming solutions.
I am solving this question right now. Here's the question -
In Byteland they have a very strange monetary system. Each Bytelandian
gold coin has an integer number written on it. A coin n can be
exchanged in a bank into three coins: n/2, n/3 and n/4. But these
numbers are all rounded down (the banks have to make a profit). You
can also sell Bytelandian coins for American dollars. The exchange
rate is 1:1. But you can not buy Bytelandian coins. You have one gold
coin. What is the maximum amount of American dollars you can get for
it?
Input
The input will contain several test cases (not more than 10). Each
testcase is a single line with a number n, 0 <= n <= 1 000 000 000. It
is the number written on your coin. Output
For each test case output a single line, containing the maximum amount
of American dollars you can make. Example
Input: 12 2
Output: 13 2 You can change 12 into 6, 4 and 3, and then change these
into $6+$4+$3 = $13. If you try changing the coin 2 into 3 smaller
coins, you will get 1, 0 and 0, and later you can get no more than $1
out of them. It is better just to change the 2 coin directly into $2.
Now I know that it's very easy. And I did get stuck initially when I was declaring a big 10^9 integer long array (Over 1GB of memory..whoo!), but coming back to my senses - I decided to do memoization till 10001, and after that simple recursion. But still - I am making a mistake, and it's giving SIGSEGV error.
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
long long n[100001];
long long calc(long long x) {
if (x < 10001) {
if(n[x] != 0) return n[x];
n[x] = max(x, calc(x/2) + calc(x/3) + calc(x/4));
return n[x];
}
else return max(x, calc(x/2) + calc(x/3) + calc(x/4));
}
int main() {
memset(n, 0, sizeof(n));
n[1] = 1;
n[2] = 2;
n[3] = 3;
n[4] = 4;
n[5] = 5;
n[6] = 6;
for (int i = 7; i < 10001; i++)
n[i] = calc(i);
int t = 10;
while (t--) {
long long c;
scanf("%lld", &c);
printf("%lld\n", calc(c));
}
return 0;
}
I have solved some previous questions too - and all of them gave me this error once or twice. I know this error means that I am trying to access memory that hasn't been allocated, but what is wrong in my approach that I always get this error?
The problem is with the corner case n=0.
calc(0) recurses indefinitely because 0<10001 and n[0]=0. You need to add the terminating condition that calc(0)=0.
Takeaways:
Always check your programming competition solutions on corner cases.
Always ensure that your recursion does not result in an infinite loop.

Time Limit Exceeded - Simple Program - Divisibility Test

Input
The input begins with two positive integers n k (n, k<=10^7). The next n lines of input contain one positive integer ti, not greater than 10^9, each.
Output
Write a single integer to output, denoting how many integers ti are divisible by k.
Example
Input:
7 3
1
51
966369
7
9
999996
11
Output:
4
My Code:
#include <iostream>
using namespace std;
int main()
{
long long n,k, i;
cin>>n;
cin>>k;
int count=0;
for(i=0;i<n;i++)
{
int z;
cin>>z;
if(z%k == 0) count++;
}
cout<<count;
return 0;
}
Now this code produces the correct output. However, its not being accepted by CodeChef(http://www.codechef.com/problems/INTEST) for the following reason: Time Limit Exceeded. How can this be further optimized?
As said by caleb the problem is labeled "Enormous Input Test" so it requires you to use some better/faster I/O methods
just replacing cout with printf and cin with scanf will give you an AC but to improve your execution time you need to use some faster IO method for example reading character by character using getchar_unlocked() will give you a better execution time
so you can read the values by using a function like this , for a better execution time.
inline int read(){
char c=getchar_unlocked();
int n=0;
while(!(c>='0' && c<='9'))
c=getchar_unlocked();
while(c>='0' && c<='9'){
n=n*10 + (c-'0');
c=getchar_unlocked();
}
return n;
}
The linked problem contains the following description:
The purpose of this problem is to verify whether the method you are
using to read input data is sufficiently fast to handle problems
branded with the enormous Input/Output warning. You are expected to be
able to process at least 2.5MB of input data per second at runtime.
Considering that, reading values from input a few bytes at a time using iostreams isn't going to cut it. I googled around a bit and found a drop-in replacement for cin and cout described on CodeChef. Some other approaches you could try include using a memory-mapped file and using stdio.
It might also help to look for ways to optimize the calculation. For example, if ti < k, then you know that k is not a factor of ti. Depending on the magnitude of k and the distribution of ti values, that observation alone could save a lot of time.
Remember: the fact that your code is short doesn't mean that it's fast.

How do I convert this function into a loop?

I have an array of letters of an unknown number of elements which contains lower case letters. I have written a function for converting a lower case number to its ASCII value
int returnVal (char x)
{
return (int) x;
}
I am trying to combine all of these values into one number. Subtracting 87 from each of these means that the value is always a 2 digit number. I am able to combine an array made up if two elements by:
returnVal (foo[0]) - 87) + returnVal (foo[1] - 87) * 100
an array made up of three elements by
returnVal (foo[0]) - 87) + returnVal (foo[1] -87) * 100 + returnVal (foo[2] - 87) * 100 * 100
I am multiplying each element by 100^its position in the array and summing them. This means that [a,b,c] would become 121110 (yes, the 'flip' having the value for 'c' first and 'a' last is intentional). Could anybody programme this (for an array of an unknown number of elements)?
EDIT: I have received no form of schooling at programming/computer science at any pojnt in my life, this is not homework. I am trying to teach myself and I have got stuck; I don't know anybody in person who I could go to for help so I asked here, apologies to those of you who are offended.
EDIT2: I know that this opinion is going to annoy a lot of people; what is the purpose of stackoverflow.com if it is not to exchange information? If I were a child who was stuck with my homework (I'm not) surely that is a valid reason for using stack overflow? Many people on this website seem to have the mindset that if a problem is asked by a beginner then it is not worth answering, which is completely fine because your time is your own. However, what genuinely bugs me is the people who see a question which they deem trivial and say "homework" and vote it down immediately. I think that this website would be far better if there wasn't an "minimum-level" knowledge required in order to ask questions, the "elitist" mindset is just childish in my opinion.
Since this is a learning exercise, here are some hints for you to complete the task yourself:
Prepare a value that will server as the "running total" for your number so far.
Start the running total at zero.
When you convert a number, say, "1234", to an int, this value would first become 1, then 12, then 123, and finally 1234
The final value of the running total is your end result
To go from a previous value to the next, multiply the prior value by ten, and add the value of the current digit to it
Your returnVal does not make sense, because in C you can very often avoid an explicit conversion of char to int. You can definitely avoid it in this case.
Making a function int digit(char c) that returns a value of decimal digit, i.e. c-'a', would be a lot more useful, because it would let you get rid of your c-87 in multiple spots.
char array[SIZE];
long factor=1;
long result=0;
for(int i=0; i<SIZE; i++)
{
result+=returnVal(foo[i])-87)*factor;
factor*=100;
}
This should work for as long as long is large enough to hold the value of 100^the position and, of course, as long as the result does not overflow.