I'm trying to create a program for an assignment that computes the rate for a long distance call, that takes in the starting time and length of call and outputs the gross cost and net cost.
There are several parameters involved, which i've implemented in conditional statements,
Any call started at or after 6:00 pm (1800) but before 8:00 am (800) is discounted 50%.
All calls are subject to a 4% federal tax.
The regular rate is $0.35 per minute.
Any call longer than 60 minutes receives a 16% discount on its cost (after any other discount is subtracted but before tax is added).
However, the first conditionals code is never executed and I've tried several different operands and still have not figured it out.
#import <iostream>
using namespace std;
int main() {
//declare variables
int startTime;
int callLength;
double grossCost = 0;
double netCost;
const double callRate = 0.35;
const double fedTax = 0.04;
const double discount1 = 0.50;
const double discount2 = 0.16;
//begin user prompt
cout << "Enter start time: " << endl;
cin >> startTime;
cout << "Enter length of call in minutes: " << endl;
cin >> callLength;
//define our grossCost
grossCost = (callLength * callRate);
//lez do some conditionals
if ((startTime >= 1800) && (startTime <= 800)){
netCost = grossCost - (grossCost * discount1);
netCost *= fedTax;
}
else if (callLength > 60){
netCost = grossCost - (grossCost * discount2);
netCost *= fedTax;
}
else{
netCost = (grossCost * fedTax);
}
//print out our final costs
cout << "gross cost : " << "$" << grossCost << endl;
cout << "net cost: " << "$" << netCost << endl;
return 0;
}
So, when trying an input of:
Enter start time: 2322
Enter length of call in minutes: 67
gross cost : $23.45
net cost: $0.78792
The netcost is not being evaluated correctly, as it is skipping the first conditional, even though the values of startTime meet the parameters.
The output should be:
Enter start time: 2322
Enter length of call in minutes: 67
gross cost: $23.45
net cost: $10.24
I'm not looking for someone to do my homework, just some pointers to lead me in the right direction, i've gone over the conditional several times and I'm still confused as to why it's not evaluating. Any help is appreciated, thanks.
You have a logic error here: a number can not be greater or equal than 1800 and less or equal than 800 at the same time. Revise the first conditional. I would break it in two parts
if((time >= 1800 & <=2400) || (time >= 0 && time <= 800)).
The actual logical mistake here is that calls after 6PM and before 8AM would exist in different days! So we do need two conditions that check on the days' boundaries as well, combined.
Edit per comment by #Reto Koradi:
The outcome won't change if we omit the boundary checks. As mentioned above, the gist of the change is to highlight the mutual exclusiveness of th two conditions, which is achieved by swapping the && out with an ||:
if (time >= 1800 || time <= 800)
The explanation why it's not working is fairly obvious, and already covered in other answers. This expression can never be true because no number is both greater than 1800 and also less than 800.
if ((startTime >= 1800) && (startTime <= 800)){
The && operator tests for both conditions to be true.
The more interesting part is why people make this mistake. And you're neither the first nor the last person to fall into this trap when starting out with logical expressions.
I believe the reason is that in natural language, we use the word "and" in ways that are very different from the logical operator. When you say "before 8 am and after 6 pm", the "and" corresponds much more to the "union" set operation. You're basically defining a set that contains "all times before 8 am" and "all times after 6 pm", which is a set union.
The logical operator that matches the "union" set operation is the logical "or". Any element that is in at least one of the input sets is part of the union. So for the union of two sets, the union is the set with elements that are in the first set or the second set.
With that understood, the correct condition is:
if ((startTime >= 1800) || (startTime <= 800)){
where || is the logical "or" operator.
Logical operations working differently from the way they are used in everyday language is not unusual at all. So you always need to be careful when translating language to logical expressions. Another popular example is that "or" in natural language mostly corresponds to an exclusive or, while the "or" operator is inclusive. So if somebody tells you that "you can take it or leave it", it means that you have to decide, while the standard logical "or" operator would actually allow you to do both.
The problem is
if ((startTime >= 1800) && (startTime <= 800)){
The two conditions are mutually exclusive. There is no number greater than 1800 and at the same time smaller than 800. You might want to fix the comparison condition like this (improved for future readers thanks to iksemyonov's comments. Please refer to his answer to this same question)
if ((startTime >= 1800) || (startTime <= 800)){
How can x > 1800 and x < 800 ever be true at the same time?. If the first is true, the statement will always be false.
Related
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 2 years ago.
Improve this question
My program needs to be able to calculate the monthly phone bill and there are 3 plans: Basic where 10 hours are free and it costs 9.95, Gold where 20 hours are free and it costs 14.95, and Platinum where you have unlimited hours and it costs 19.95. When my program is given hours less than the free hours it subtracts them from the initial cost, and also it has build hours.
#include <iostream>
#include <string>
using namespace std;
int main()
{
//Set up the variables.
string input;
int hours;
int basicHours;
int goldHours;
float extraBasic;
float basicCost;
float goldCost;
// Will ask and display the user their plan and hours.
cout << "Hello! Welcome to the Comms4You Telecom Company!" << endl;
cout << "Please provide your plan." << endl;
cin >> input;
cout << input << ", Ok now please provide the amount of hours you used." << endl;
cin >> hours;
//Calculate different equations
basicHours = (hours - 10);
goldHours = (20 - hours);
extraBasic = (basicHours * 2);
basicCost = (9.95 + extraBasic);
goldCost = (14.95 + goldHours);
//This part is for displaying to the users plans and hours.(Also calculations)
if (input == "Platinum") {
cout << "Our company thanks you for using " << hours << " hours! " << "Your total cost is $19.95.";
}
else if (input == "Gold") {
cout << "Our company thanks you for using " << hours << " hours! " << "Your total cost is $" << goldCost << ".";
}
else if (input == "Basic") {
cout << "Our company thanks you for using " << hours << " hours! " << "Your total cost is $" << basicCost << ".";
}
else
return 0;
}
The problem is in these lines:
basicHours = (hours - 10);
goldHours = (20 - hours);
extraBasic = (basicHours * 2);
basicCost = (9.95 + extraBasic);
goldCost = (14.95 + goldHours);
Think about what they are doing.
basicHours = (hours - 10);
If hours was 11, then basicHours is now 11 - 10 = 1. This is good. But if hours was 9, then basicHours is now 9 - 10 = -1. This is not what you want; if I used less than my 10 free hours, then you want basicHours to be 0.
So you can write instead:
if (hours > 10) {
basicHours = hours - 10;
}
else {
basicHours = 0;
}
or equivalently:
basicHours = (hours > 10) ? hours - 10 : 0;
goldHours = (20 - hours)
This should be the exact same thing as basicHours, except with 20 instead of 10! I will let you adapt the above code.
basicCost = (9.95 + extraBasic); and goldCost = (14.95 + goldHours);
This is wrong. 9.95 is a monetary value, say in euros. extraBasic is a time, in hours. You cannot add hours with euros! If I used 12 hours with the basic plan, what is the result of 9.95€ + 2h? I do not know, it does not make sense.
If I used 12 hours with the basic plan, then I have to pay 9.95€, and I have to pay for the extra 2h. What is the cost of the extra 2h? It is 2 times the cost of an hour; in other words, it's the extra time multiplied by the hourly rate. You should have a constant variable called hourlyRate or basicHourlyRate in your program, with that value. Then you can write:
basicCost = 9.95 + extraBasic * basicHourlyRate;
goldCost = 14.95 + goldHours * goldHourlyRate;
Coding style: separate data and code
A good rule to follow is never to put data in your code. All literal values are data. The cost of the basic and gold and platinum plans are data. The hourly rate is data. The number of "free" hours for each plan is data. Define a few variables with explicit names, initialize those variables with the data at the very beginning of the code, then write the rest of the code without ever using a literal value. There are two reasons why this is important.
The code will be easier to read with variables. Explicit names in variables make the code meaningful; if you use literal values inside the code, the people reading your code don't know what those values stand for. Why do you subtract 10 from hours? We have to think about where this 10 comes from. However, if you write basicPayingHours = hours - freeBasicHours, we understand immediately. "The people reading your code" include StackOverflow members you're showing your code to, but also your schoolmates or coworkers, your teacher or boss, and most importantly, yourself when you read your code again six months from now.
When the data changes, it will be a lot easier to update your code if data is cleanly separated from code. Imagine you are working for this phone company. Next year, they update their plans and the basic plan is now 9.99 per month instead of 9.95. If this value is stored at the beginning of your code in a line basicPlanInitialCost = 9.95;, it is very easy to update it. However if there are multiple occurrences of 9.95 in your code, you will have to track them and change them all manually - this process is very prone to errors for two reasons: you might accidentally change the cost of something else that also costs 9.95; you might forget to update values that are dependent on the monthly price of the basic cost (like the yearly price of the basic cost, which is 12 * 9.95 = 119.40).
I started working on a problem in the past several days...
A company plans its business in a three month period. It can produce
110 units at a cost of 600 each. The minimum amount it must produce
per month is 15 units if active (but of course, it can choose to be closed
during the month, and produce 0 units). Each month it can subcotract the
prodution of 60 units, at a cost of 660 each. Storing a unit for one month
costs 20$ per unit per month. The marketing department has forcasted
sales of 100, 130 and 150 units for the next three months, respectively.
The goal is to meet the demand each month while minimizing the total
cost.
I deduced that we need to have an objective function of form min[Sum(i=0..3) 600*x1+660*x2+20*x3].
We need to add some constrains on x1>=15, and on x2 0<=x2<=60
Also we will also need another constraint for each month...
For the first one i=1 => x1+x2 = 100 - x3last (x3last is an extra variable that should hold the amount existing in deposit from the previous month), and for i=2 and i=3 same constraints.
I don't have any idea how to write this in pulp, and i would appreciate some help. Thx ^_^
I'd tend to agree with #Erwin that you should focus on formulating the problem as a Linear Program. It is then easy to translate this into code in PULP or one of many other PULP libraries/tools/languages.
As an example of this - lets work through this process for the example problem you have written out in your question.
Decision Variables
The first thing to decide is what you can/should decide. This set of information is called the decision variables. Picking the best/easiest decision variables for your problem comes with practice - the important thing is that once you know the values of the variables you have a unique solution to the problem.
Here I would suggest the following. These assume that the forecasts for demand are perfect. For each month i:
Whether the production line should be open - o[i]
How much to produce in that month - p[i]
How much to hold in storage for next month - s[i]
How much to get made externally - e[i]
Objective Function
The objective in your case is obvious - minimise the total cost. So we can just write this down: sum(i=0...2)[p[i]*600 + s[i]*20 + e[i]*660]
Constraints
Let's lift these directly our of your problem description:
"It can produce 110 units at a cost of 600 each. The minimum amount it must produce per month is 15 units if active (but of course, it can choose to be closed during the month, and produce 0 units)."
p[i] >= o[i]*15
p[i] <= o[i]*110
The first constraint forces the minimum production about to be 15 if the production is open that month (o[i] == 1), if the production is not open this constraint has not effect. The second constraint sets a maximum value on p[i] of 110 if the production is open and a maximum production of 0 if the production is closed that month (o[i] == 0).
"Each month it can subcotract the prodution of 60 units, at a cost of 660 each"
e[i] <= 60
"The marketing department has forcasted sales of 100, 130 and 150 units for the next three months, respectively. The goal is to meet the demand each month while minimizing the total cost." If we declare the sales in each mongth to be sales[i], we can define our "flow constraint" as:
p[i] + e[i] + s[i-1] == s[i] + sales[i]
The way to think of this constraint is inputs on the left, and outputs on the right. Inputs of units are production, external production, and stuff taken out of storage from last month. Outputs are units left/put in storage for next month and sales.
Finally in code:
from pulp import *
all_i = [1,2,3]
all_i_with_0 = [0,1,2,3]
sales = {1:100, 2:130, 3:150}
o = LpVariable.dicts('open', all_i, cat='Binary')
p =LpVariable.dicts('production', all_i, cat='Linear')
s =LpVariable.dicts('stored', all_i_with_0, lowBound=0, cat='Linear')
e =LpVariable.dicts('external', all_i, lowBound=0, cat='Linear')
prob = LpProblem("MinCost", LpMinimize)
prob += lpSum([p[i]*600 + s[i]*20 + e[i]*660 for i in all_i]) # Objective
for i in all_i:
prob += p[i] >= o[i]*15
prob += p[i] <= o[i]*110
prob += e[i] <= 60
prob += p[i] + e[i] + s[i-1] == sales[i] + s[i]
prob += s[0] == 0 # No stock inherited from previous monts
prob.solve()
# The status of the solution
print ("Status:", LpStatus [prob.status])
# Dislay the optimums of each var
for v in prob.variables ():
print (v.name, "=", v.varValue)
# Objective fcn
print ("Obj. Fcn: ", value(prob.objective))
Which returns:
Status: Optimal
external_1 = 0.0
external_2 = 10.0
external_3 = 40.0
open_1 = 1.0
open_2 = 1.0
open_3 = 1.0
production_1 = 110.0
production_2 = 110.0
production_3 = 110.0
stored_0 = 0.0
stored_1 = 10.0
stored_2 = 0.0
stored_3 = 0.0
Obj. Fcn: 231200.0
I'm currently trying to solve a programming problem that involves different ranges of values that overlap. The task is to accept input, in E-notation, and that is where the overlap of range inevitably occurs.
I have 2 ranges that overlap at 1E-11. 1E-11 and lower and 1E-11 and higher
The output would be 1E-11 is either x or it is y. Programmatically i would solve it like this:
(X_MIN would be 1E-11 and X_MAX 1E-8)
(Y_MAX would be 1E-11 and Y_MIN 1E-13)
(lengthOfRange <= X_MIN) && (lengthOfRange >= Y_MAX) ?
cout << "This value entered indicates that it is x\n" :
cout << "It is y";
Expressed this way if i input IE-11 it shows me "This value entered indicates ..." but will never show me it is y (understandably - overlap!)
The other way around would be expressing it this way:
(lengthOfRange <= X_MIN) && (lengthOfRange != Y_MAX) ?
cout << "This value entered indicates that it is x\n" :
cout << "It is y";
The output would always be "... It is y ..." (Same difference - overlap!) There is no other determining factor that would tell range is x or y coming in to play there as of right now.
...
if (lengthOfRange <= X_MIN) && (lengthOfRange == Y_MAX)
{
cout << "The input indicates that it could be either x or y\n";
}
...
Even if i were to solve the problem in a way such as defining the range with different values, would in the end lead to the very same problem. I COULD define MIN and MAX as constants in lengthOfFrequency, which is totally different, bit then i would have to say: lengthOfFrequency = 1E-11; and voila same problem once again. 1 input 2 ranges that are technically different, getting the same one and only correct value in E-notation.
Is there a way around this without involving to simply say input is either x || y? Which it is technically of course, and if it were to be solved physically there are ways of telling it apart that 1E-11 is not 1E-11 though it is. (I hope i make sense here). But, again, ... is there such way, and how would i go about writing it? (Not asking for code specifically though it would be highly welcome, just a pointer in the right direction.) Or should i rather go with saying input is either x || y?
Thanks in advance for any answer!
**Minimum Complete Code:**
#include <iostream>
using std::cout;
using std::cin;
int main()
{
/* Constants for ranges, min and max */
const double X_RAYS_MIN = 1E-13,
X_RAYS_MAX = 1E-11,
Y_RAYS_MIN = 1E-11,
Y_RAYS_MAX = 1E-8,
Z_RAYS_MIN = 1E-7,
Z_RAYS_MAX = 3.8E-7;
double lengthOfRange;
/* Test output and validation */
cout << "Enter value in scientifc notation: ";
cin >> lengthOfRange;
/* X_RAYS_MIN < is 1E-14, 1E-15, 1E-16 etc. > 1E-12, 1E-11 etc.. */
if (lengthOfRange >= X_RAYS_MIN && lengthOfRange <= X_RAYS_MAX)
{
cout << "X_RAYS\n";
}
else if (lengthOfRange >= Y_RAYS_MIN && lengthOfRange <= Y_RAYS_MAX)
{
cout << "Y_RAYS\n";
}
system("pause");
return 0;
}
Output is: 1E-10 is Y_RAYS, 1E-9 is Y_RAYS, 1E-11 X_RAYS, 1E-12 X_RAYS
Somehow i found the solution for my problem myself without going any roundabout ways ... By hovering over the 1E-13:
X_RAYS_MIN = 1E-13
VS showed me 1.(numberofzeros)3E-13, and guess what ... if instead the input for 1E-11 is 2E-11, the output for X_RAYS becomes Y_RAYS ... so the problem "magically" solved itself ... lucky me i guess ... :)
I'm trying to use a conditional statement that does one thing in one condition but does two things if the other condition applies.
Consider the following:
( h >= 0 && h < 24 ? hour = h : hour = 0, cout << "Invalid Hour Detected\n")
If "h" is set to 25, it sets "hour" to 0 correctly.
If "h" is set to 12, it correctly sets "hour" to 12.
The problem is that it outputs "Invalid Hour Detected" for both true and false conditions.
I only want it to output if the conditions aren't met.
Essentially, I'm wondering if it is possible in a conditional statement to do two things for one condition.
Also tried:
( h >= 0 && h < 24 ? hour = h : hour = 0 && cout << "Invalid Hour Detected\n")
but that didn't run the cout on either case.
If you really want to do this, add proper parentheses and invert the order of the assignment and the output insertion (when using the comma operator, the value of the left expression is discarded):
( h >= 0 && h < 24 ) ? ( hour = h ) : (std::cout << "Invalid Hour Detected\n", hour = 0);
However, my advice is to make your code readable and abandon this kind of coding style.
I'm trying to use a conditional statement that does one thing in one condition but does two things if the other condition applies.
That's not a conditional statement, it's a conditional expression+. Conditional statement would be a lot more appropriate here from the readability perspective:
if( h >= 0 && h < 24) {
hour = h;
} else {
hour = 0;
cout << "Invalid Hour Detected\n";
}
+ C++ follows C in allowing use of standalone expressions as statements. That's why you can eventually "shoehorn" your solution into the right syntax by using parentheses and switching the order of operations. The readability of that solution suffers a lot compared to that of a plain, familiar if.
Try
( h >= 0 && h < 24 ? hour = h : (hour = 0 || cout << "Invalid Hour Detected\n"))
Or
( h >= 0 && h < 24 ? hour = h : (hour = 0 & cout << "Invalid Hour Detected\n"))
The comma operator has the lowest precedence of all the operators. Consequently, your expression is evaluated like this:
(( h >= 0 && h < 24 ? hour = h : hour = 0), cout << "Invalid Hour Detected\n")
You could express this in a conditional expression, with grouping and proper usage of the comma operator. But, if at all possible, it would be better to express this in an if/else statement. If you need to use it in an expression, consider placing it in a function.
Well I know that this is probably not the answer you are looking for but if you refactored a little this would be cleared up "naturally".
// Handy as a utility free function (in apt namespace)
bool isValidHour(unsigned int hour) {
return hour >= 0 && hour < 24;
}
isValidHour(h) ? hour = h : handleInvalidHour();
//...more
// If this is not in a class then you should pass "hour" as a reference.
void MyClass::handleInvalidHour() {
hour = 0;
cout << "Invalid Hour Detected\n";
}
Of course you should be using the new std::chrono stuff if possible. It's lovely and expressive.
I am trying to make a call billing program in c++. One of the features of this small program is the ability to update discount minutes spoken within discount hours and normal-priced minutes during business hours, depending on which time stretch is entered.
The user first enters the time as a string like this 22:00
Then I have a function which takes the string and turns it into an integer. For example the 22:00 above is turned into 2200
I have then another help function that takes an int, the int above and turns it to the decimal time.
double turnTimeToDecimal(int timeRaw){
double decimalTime;
decimalTime = timeRaw * 0.01;
return decimalTime;
}
The business hours which bear no discount and are between 8.00 am and 18.30am in order to deal with this feature I update two counters inside a for loop that goes from 0 to 1417minutes (24hrs):
double myStartDecimal = 0.0;
double myStopDecimal = 0.0;
myStartDecimal = turnTimeToDecimal(myStartRaw);
myStopDecimal = turnTimeToDecimal(myStopRaw);
//hours and minutes start
int hourStart = (int)floor(myStartDecimal);
int minuteStart = (int)round(100*(myStartDecimal - hourStart));
//hours and minutes stop
int hourStop = (int)floor(myStopDecimal);
int minuteStop = (int) round(100*(myStopDecimal - hourStop));
int totalMinutesPremium = 0;
int totalMinutesDiscount = 0;
int i = 0;
int k = 0;
for(k = (hourStart* 60) + minuteStart; k < (hourStop * 60) + minuteStop + round(((double)minuteStop/100)); k++){
//will update the corresponding counter depending
//on the time stretch, business hours 8.00 - 18.30.
if(hourStart >= 8 && hourStop < 18.5){
totalMinutesPremium++;
}else{
totalMinutesDiscount++;
}
}
//will give total minutes
cout << " k is: " << k << endl;
//will give the total number of minutes during the business hours and
//the total number of minutes during the discount hours(non-bussiness hours)
cout << "Total minutes premium " << round(totalMinutesPremium) <<
" Total Minutes discount " << round(totalMinutesDiscount) << endl;
However, the program does detects whether the time stretch entered is within business hours or not, except in one case. If the time for example lies between 7:30 and 8:30 (business hours between 7:59-18:30) it does not return the combination of minutes within the business hours which I would expect to be 30 min and minutes within the discount hours which I would expect to be 30 minutes as well, since the discount stretch ends at 07:59 and it starts again at 18:31.
Hopefully I made myself clear.
Inside the for loop, you allocate the given minute depending on hourStart and hourStop, not on whether the given minute is during business hours. If the call encroaches on discount hours, then the whole call will be discounted.
"However HourStop is an int. same thing goes for hourStart"
Then it's not going to work, if can't use decimal values with ints like you do here:
hourStop < 18.5
well.. you can but it's not going to work the way you want it to. If you have int hourStop = 18.5 then it's going to get truncated to 18 since it can't be a fractional number. You need to use a different type, such as double
Also, the condition in your loop depends on hourStart and hourStop which are never changing in the loop:
if(hourStart >= 8 && hourStop < 18.5){
So you'll always hit the same if condition (which ever it is)
Why use a loop? Why not just do the math?
While not the complete code answer... you can fill in the blanks...
if( startTime >= startOfPremiumPeriod && endTime <= endOfPremiumPeriod )
totalMinutesPremimum = endTime - startTime;
else if( startTime < startOfPremiumPeriod && endTime < startOfPremimumPeriod )
totalMinutesDiscount = endTime - startTime;
.... etc. etc. etc.
You can take into account the case where the start time is before midnight and the end time after midnight by adding 24 hours to the end time...
if( endTime < startTime ) endTime += 1440;