Calculating tips
I am enrolled in an online JavaScript course and one of our coding challenges was presented as follows:
John and his family went on a holiday and went to 3 different restaurants. The bills were $124, $48, and $268.
To tip the waiter a fair amount, John created a simple tip calculator (as a function). He likes to tip 20% of the bill when the bill is less than $50,
15% when the bill is between $50 and $200, and 10% if the bill is more than $200.
In the end, John would like to have 2 arrays:
- Containing all three tips (one for each bill)
- Containing all three final paid amounts (bill + tip)
I have come up with the following solution:
var bills = [124, 48, 268];
var totals = ;
var pointlessArray = ;
function calculateTip(cost) {
switch (true) {
case cost < 50:
return cost * .2;
break;
case cost > 49 && cost < 201:
return cost * .15;
break;
case cost > 200:
return cost * .1;
break;
default:
Error('Unsupported input.');
}
}
function makePointlessArray(inputArray) {
var length = inputArray.length;
for (var i = 0; i < length; i++) {
pointlessArray[i] = calculateTip(inputArray[i]);
}
}
function calculateTotal(billArray) {
var length = billArray.length;
for (var i = 0; i < length; i++) {
totals[i] = billArray[i] + calculateTip(billArray[i]);
}
}
makePointlessArray(bills);
calculateTotal(bills);
console.log(`The bills are: ${bills}`);
console.log(`The calculated tips are: ${pointlessArray}`);
console.log(`The calculated totals are: ${totals}`);
I don't think this is practical at all for calculating tips, but have tried to stay within the parameters of the challenge.
I am unsure if declaring the arrays as global variables is the best practice or if some other method should be used, but as a JS newbie I would appreciate any input on pitfalls in my code.
javascript homework
New contributor
add a comment |
I am enrolled in an online JavaScript course and one of our coding challenges was presented as follows:
John and his family went on a holiday and went to 3 different restaurants. The bills were $124, $48, and $268.
To tip the waiter a fair amount, John created a simple tip calculator (as a function). He likes to tip 20% of the bill when the bill is less than $50,
15% when the bill is between $50 and $200, and 10% if the bill is more than $200.
In the end, John would like to have 2 arrays:
- Containing all three tips (one for each bill)
- Containing all three final paid amounts (bill + tip)
I have come up with the following solution:
var bills = [124, 48, 268];
var totals = ;
var pointlessArray = ;
function calculateTip(cost) {
switch (true) {
case cost < 50:
return cost * .2;
break;
case cost > 49 && cost < 201:
return cost * .15;
break;
case cost > 200:
return cost * .1;
break;
default:
Error('Unsupported input.');
}
}
function makePointlessArray(inputArray) {
var length = inputArray.length;
for (var i = 0; i < length; i++) {
pointlessArray[i] = calculateTip(inputArray[i]);
}
}
function calculateTotal(billArray) {
var length = billArray.length;
for (var i = 0; i < length; i++) {
totals[i] = billArray[i] + calculateTip(billArray[i]);
}
}
makePointlessArray(bills);
calculateTotal(bills);
console.log(`The bills are: ${bills}`);
console.log(`The calculated tips are: ${pointlessArray}`);
console.log(`The calculated totals are: ${totals}`);
I don't think this is practical at all for calculating tips, but have tried to stay within the parameters of the challenge.
I am unsure if declaring the arrays as global variables is the best practice or if some other method should be used, but as a JS newbie I would appreciate any input on pitfalls in my code.
javascript homework
New contributor
So the waiter gets more money if the bill is $49 than if it’s $51? Weird... :)
– Cris Luengo
Dec 20 at 22:04
add a comment |
I am enrolled in an online JavaScript course and one of our coding challenges was presented as follows:
John and his family went on a holiday and went to 3 different restaurants. The bills were $124, $48, and $268.
To tip the waiter a fair amount, John created a simple tip calculator (as a function). He likes to tip 20% of the bill when the bill is less than $50,
15% when the bill is between $50 and $200, and 10% if the bill is more than $200.
In the end, John would like to have 2 arrays:
- Containing all three tips (one for each bill)
- Containing all three final paid amounts (bill + tip)
I have come up with the following solution:
var bills = [124, 48, 268];
var totals = ;
var pointlessArray = ;
function calculateTip(cost) {
switch (true) {
case cost < 50:
return cost * .2;
break;
case cost > 49 && cost < 201:
return cost * .15;
break;
case cost > 200:
return cost * .1;
break;
default:
Error('Unsupported input.');
}
}
function makePointlessArray(inputArray) {
var length = inputArray.length;
for (var i = 0; i < length; i++) {
pointlessArray[i] = calculateTip(inputArray[i]);
}
}
function calculateTotal(billArray) {
var length = billArray.length;
for (var i = 0; i < length; i++) {
totals[i] = billArray[i] + calculateTip(billArray[i]);
}
}
makePointlessArray(bills);
calculateTotal(bills);
console.log(`The bills are: ${bills}`);
console.log(`The calculated tips are: ${pointlessArray}`);
console.log(`The calculated totals are: ${totals}`);
I don't think this is practical at all for calculating tips, but have tried to stay within the parameters of the challenge.
I am unsure if declaring the arrays as global variables is the best practice or if some other method should be used, but as a JS newbie I would appreciate any input on pitfalls in my code.
javascript homework
New contributor
I am enrolled in an online JavaScript course and one of our coding challenges was presented as follows:
John and his family went on a holiday and went to 3 different restaurants. The bills were $124, $48, and $268.
To tip the waiter a fair amount, John created a simple tip calculator (as a function). He likes to tip 20% of the bill when the bill is less than $50,
15% when the bill is between $50 and $200, and 10% if the bill is more than $200.
In the end, John would like to have 2 arrays:
- Containing all three tips (one for each bill)
- Containing all three final paid amounts (bill + tip)
I have come up with the following solution:
var bills = [124, 48, 268];
var totals = ;
var pointlessArray = ;
function calculateTip(cost) {
switch (true) {
case cost < 50:
return cost * .2;
break;
case cost > 49 && cost < 201:
return cost * .15;
break;
case cost > 200:
return cost * .1;
break;
default:
Error('Unsupported input.');
}
}
function makePointlessArray(inputArray) {
var length = inputArray.length;
for (var i = 0; i < length; i++) {
pointlessArray[i] = calculateTip(inputArray[i]);
}
}
function calculateTotal(billArray) {
var length = billArray.length;
for (var i = 0; i < length; i++) {
totals[i] = billArray[i] + calculateTip(billArray[i]);
}
}
makePointlessArray(bills);
calculateTotal(bills);
console.log(`The bills are: ${bills}`);
console.log(`The calculated tips are: ${pointlessArray}`);
console.log(`The calculated totals are: ${totals}`);
I don't think this is practical at all for calculating tips, but have tried to stay within the parameters of the challenge.
I am unsure if declaring the arrays as global variables is the best practice or if some other method should be used, but as a JS newbie I would appreciate any input on pitfalls in my code.
var bills = [124, 48, 268];
var totals = ;
var pointlessArray = ;
function calculateTip(cost) {
switch (true) {
case cost < 50:
return cost * .2;
break;
case cost > 49 && cost < 201:
return cost * .15;
break;
case cost > 200:
return cost * .1;
break;
default:
Error('Unsupported input.');
}
}
function makePointlessArray(inputArray) {
var length = inputArray.length;
for (var i = 0; i < length; i++) {
pointlessArray[i] = calculateTip(inputArray[i]);
}
}
function calculateTotal(billArray) {
var length = billArray.length;
for (var i = 0; i < length; i++) {
totals[i] = billArray[i] + calculateTip(billArray[i]);
}
}
makePointlessArray(bills);
calculateTotal(bills);
console.log(`The bills are: ${bills}`);
console.log(`The calculated tips are: ${pointlessArray}`);
console.log(`The calculated totals are: ${totals}`);
var bills = [124, 48, 268];
var totals = ;
var pointlessArray = ;
function calculateTip(cost) {
switch (true) {
case cost < 50:
return cost * .2;
break;
case cost > 49 && cost < 201:
return cost * .15;
break;
case cost > 200:
return cost * .1;
break;
default:
Error('Unsupported input.');
}
}
function makePointlessArray(inputArray) {
var length = inputArray.length;
for (var i = 0; i < length; i++) {
pointlessArray[i] = calculateTip(inputArray[i]);
}
}
function calculateTotal(billArray) {
var length = billArray.length;
for (var i = 0; i < length; i++) {
totals[i] = billArray[i] + calculateTip(billArray[i]);
}
}
makePointlessArray(bills);
calculateTotal(bills);
console.log(`The bills are: ${bills}`);
console.log(`The calculated tips are: ${pointlessArray}`);
console.log(`The calculated totals are: ${totals}`);
javascript homework
javascript homework
New contributor
New contributor
edited Dec 20 at 17:44
Sᴀᴍ Onᴇᴌᴀ
8,33261853
8,33261853
New contributor
asked Dec 20 at 15:57
Jesse_b
1135
1135
New contributor
New contributor
So the waiter gets more money if the bill is $49 than if it’s $51? Weird... :)
– Cris Luengo
Dec 20 at 22:04
add a comment |
So the waiter gets more money if the bill is $49 than if it’s $51? Weird... :)
– Cris Luengo
Dec 20 at 22:04
So the waiter gets more money if the bill is $49 than if it’s $51? Weird... :)
– Cris Luengo
Dec 20 at 22:04
So the waiter gets more money if the bill is $49 than if it’s $51? Weird... :)
– Cris Luengo
Dec 20 at 22:04
add a comment |
2 Answers
2
active
oldest
votes
break
statements after return
While it is a great habit to include the break
statements, there is no need to include break
statements following a return
, since anything following the return
statement within a function is unreachable.
switch(true)
while this works because each case
statement must evaluate to true, it is simpler to just use if
statements. Your logic checks if the value is less than 50, then if it is greater than 49 and less than 201. The requirements never specified if the values would be integers, floats, etc. So it would be wise to consider a value like 49.5. That value would be less than 50 so the first condition would be true. However if the value was $200.50 the second condition would evaluate to true, even though the value was more than 200. So update the condition to cost <= 200
. Otherwise if neither of those conditions have been met, the value must be more than 200.
function calculateTip(cost) {
if (cost < 50) {
return cost * .2;
}
if (cost <= 200) {
return cost * .15;
}
return cost * .1;
}
Error
The default case of the switch statement merely calls Error
default:
Error('Unsupported input.');
This likely won't do what you expect. If you want an error to be thrown, then instantiate an error with the new
operator and precede it with the throw
operator:
throw new Error('Unsupported input.');
It would be wise the check the input before comparing the value against other numbers, perhaps with the parseFloat()
function:
function calculateTip(cost) {
if (!parseFloat(cost)) {
throw new Error('Unsupported input.');
}
That way anything that cannot be coerced the an integer (e.g. {}
) will cause the error to be thrown.
Updated code
See the code below with the advice above implemented.
var bills = [124, 48, 268];
var totals = ;
var pointlessArray = ;
function calculateTip(cost) {
if (!parseFloat(cost)) {
throw new Error('Unsupported input.');
}
if (cost < 50) {
return cost * .2;
}
if (cost <= 200) {
return cost * .15;
}
return cost * .1;
}
function makePointlessArray(inputArray) {
var length = inputArray.length;
for (var i = 0; i < length; i++) {
pointlessArray[i] = calculateTip(inputArray[i]);
}
}
function calculateTotal(billArray) {
var length = billArray.length;
for (var i = 0; i < length; i++) {
totals[i] = billArray[i] + calculateTip(billArray[i]);
}
}
makePointlessArray(bills);
calculateTotal(bills);
console.log(`The bills are: ${bills}`);
console.log(`The calculated tips are: ${pointlessArray}`);
console.log(`The calculated totals are: ${totals}`);
1
You forgot that cash money does not exchange in fractions of a cent. Doubles and cash do not mix well.... The OP's questions question is a classic "don't forget to round" trap.
– Blindman67
Dec 22 at 0:16
add a comment |
There's a small bug in your code: a bill of $200.50 will be tipped at the wrong amount since you are testing for cost < 201
.
It's probably easier to just us if
s that are sorted and return the tip from the function on the first one that passes. That avoids the need to test ranges like cost > 49 && cost < 201
. If there were lots of categories you could make a lookup table that would work like this:
const tiptable = [
{min: 200, tip: .1},
{min: 50, tip: .15},
{min: 0, tip: .2}
]
let cost = 51
let tip = tiptable.find(tip => cost > tip.min).tip
console.log(tip)
`find()` will give you the first object that matches. But that only makes sense if there are enough categories that `if` statement get unwieldy.
find()
will give you the first object that matches. But that only makes sense if there are enough categories that if
statement get unwieldy.
Other parts of the code can be simplified with some of the nice functional tools javascript gives us. You can make a one-line sum using reduce()
and you can make an array of tips using map()
allowing you to make the arrays directly without for
loops.
For example:
const bills = [124, 48, 268];
function getTip(cost){
if (cost < 50) return .2
if (cost <= 200) return .15 // not clear whether this should be < or <=
return .1
}
let with_tip = bills.map(cost => cost + cost * getTip(cost) )
let sum = with_tip.reduce((total, n) => total + n)
console.log('Bills with tip: ', with_tip.map(t => t.toLocaleString("en-US", {style: 'currency', currency: 'USD'})))
console.log('Total:', sum.toLocaleString("en-US", {style: 'currency', currency: 'USD'}))
Also, just as an example I added nicely-formatted currency strings with toLocaleString
.
Great answer +1 Would give another +1 for thetiptable
if I could (BTW should betipTable
) and +1 fortoLocaleString
. One tiny problem. What if there are 6 bills of $6.06 each. Your code reports the total as $43.63 which is not a factor of 6, who gets the extra cent? The correct answer is $43.62 with each tip being the same amount. Money values are discrete and you have forgotten to round to nearest cent each time you do a calculation. Always work in whole cents rounding each calculation or you will end up trying to split fractions of a cent.
– Blindman67
Dec 21 at 23:47
Yes, that a great point @Blindman67 and I totally agree about working with whole cents.
– MarkM
Dec 21 at 23:49
It would be wise to disclose that ecmascript-6 features like arrow functions andlet
/const
have certain browser compatibilities to be aware of- while most modern browsers support them, certain users might be using legacy browsers
– Sᴀᴍ Onᴇᴌᴀ
Dec 22 at 0:40
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Jesse_b is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f210059%2fcalculating-tips%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
break
statements after return
While it is a great habit to include the break
statements, there is no need to include break
statements following a return
, since anything following the return
statement within a function is unreachable.
switch(true)
while this works because each case
statement must evaluate to true, it is simpler to just use if
statements. Your logic checks if the value is less than 50, then if it is greater than 49 and less than 201. The requirements never specified if the values would be integers, floats, etc. So it would be wise to consider a value like 49.5. That value would be less than 50 so the first condition would be true. However if the value was $200.50 the second condition would evaluate to true, even though the value was more than 200. So update the condition to cost <= 200
. Otherwise if neither of those conditions have been met, the value must be more than 200.
function calculateTip(cost) {
if (cost < 50) {
return cost * .2;
}
if (cost <= 200) {
return cost * .15;
}
return cost * .1;
}
Error
The default case of the switch statement merely calls Error
default:
Error('Unsupported input.');
This likely won't do what you expect. If you want an error to be thrown, then instantiate an error with the new
operator and precede it with the throw
operator:
throw new Error('Unsupported input.');
It would be wise the check the input before comparing the value against other numbers, perhaps with the parseFloat()
function:
function calculateTip(cost) {
if (!parseFloat(cost)) {
throw new Error('Unsupported input.');
}
That way anything that cannot be coerced the an integer (e.g. {}
) will cause the error to be thrown.
Updated code
See the code below with the advice above implemented.
var bills = [124, 48, 268];
var totals = ;
var pointlessArray = ;
function calculateTip(cost) {
if (!parseFloat(cost)) {
throw new Error('Unsupported input.');
}
if (cost < 50) {
return cost * .2;
}
if (cost <= 200) {
return cost * .15;
}
return cost * .1;
}
function makePointlessArray(inputArray) {
var length = inputArray.length;
for (var i = 0; i < length; i++) {
pointlessArray[i] = calculateTip(inputArray[i]);
}
}
function calculateTotal(billArray) {
var length = billArray.length;
for (var i = 0; i < length; i++) {
totals[i] = billArray[i] + calculateTip(billArray[i]);
}
}
makePointlessArray(bills);
calculateTotal(bills);
console.log(`The bills are: ${bills}`);
console.log(`The calculated tips are: ${pointlessArray}`);
console.log(`The calculated totals are: ${totals}`);
1
You forgot that cash money does not exchange in fractions of a cent. Doubles and cash do not mix well.... The OP's questions question is a classic "don't forget to round" trap.
– Blindman67
Dec 22 at 0:16
add a comment |
break
statements after return
While it is a great habit to include the break
statements, there is no need to include break
statements following a return
, since anything following the return
statement within a function is unreachable.
switch(true)
while this works because each case
statement must evaluate to true, it is simpler to just use if
statements. Your logic checks if the value is less than 50, then if it is greater than 49 and less than 201. The requirements never specified if the values would be integers, floats, etc. So it would be wise to consider a value like 49.5. That value would be less than 50 so the first condition would be true. However if the value was $200.50 the second condition would evaluate to true, even though the value was more than 200. So update the condition to cost <= 200
. Otherwise if neither of those conditions have been met, the value must be more than 200.
function calculateTip(cost) {
if (cost < 50) {
return cost * .2;
}
if (cost <= 200) {
return cost * .15;
}
return cost * .1;
}
Error
The default case of the switch statement merely calls Error
default:
Error('Unsupported input.');
This likely won't do what you expect. If you want an error to be thrown, then instantiate an error with the new
operator and precede it with the throw
operator:
throw new Error('Unsupported input.');
It would be wise the check the input before comparing the value against other numbers, perhaps with the parseFloat()
function:
function calculateTip(cost) {
if (!parseFloat(cost)) {
throw new Error('Unsupported input.');
}
That way anything that cannot be coerced the an integer (e.g. {}
) will cause the error to be thrown.
Updated code
See the code below with the advice above implemented.
var bills = [124, 48, 268];
var totals = ;
var pointlessArray = ;
function calculateTip(cost) {
if (!parseFloat(cost)) {
throw new Error('Unsupported input.');
}
if (cost < 50) {
return cost * .2;
}
if (cost <= 200) {
return cost * .15;
}
return cost * .1;
}
function makePointlessArray(inputArray) {
var length = inputArray.length;
for (var i = 0; i < length; i++) {
pointlessArray[i] = calculateTip(inputArray[i]);
}
}
function calculateTotal(billArray) {
var length = billArray.length;
for (var i = 0; i < length; i++) {
totals[i] = billArray[i] + calculateTip(billArray[i]);
}
}
makePointlessArray(bills);
calculateTotal(bills);
console.log(`The bills are: ${bills}`);
console.log(`The calculated tips are: ${pointlessArray}`);
console.log(`The calculated totals are: ${totals}`);
1
You forgot that cash money does not exchange in fractions of a cent. Doubles and cash do not mix well.... The OP's questions question is a classic "don't forget to round" trap.
– Blindman67
Dec 22 at 0:16
add a comment |
break
statements after return
While it is a great habit to include the break
statements, there is no need to include break
statements following a return
, since anything following the return
statement within a function is unreachable.
switch(true)
while this works because each case
statement must evaluate to true, it is simpler to just use if
statements. Your logic checks if the value is less than 50, then if it is greater than 49 and less than 201. The requirements never specified if the values would be integers, floats, etc. So it would be wise to consider a value like 49.5. That value would be less than 50 so the first condition would be true. However if the value was $200.50 the second condition would evaluate to true, even though the value was more than 200. So update the condition to cost <= 200
. Otherwise if neither of those conditions have been met, the value must be more than 200.
function calculateTip(cost) {
if (cost < 50) {
return cost * .2;
}
if (cost <= 200) {
return cost * .15;
}
return cost * .1;
}
Error
The default case of the switch statement merely calls Error
default:
Error('Unsupported input.');
This likely won't do what you expect. If you want an error to be thrown, then instantiate an error with the new
operator and precede it with the throw
operator:
throw new Error('Unsupported input.');
It would be wise the check the input before comparing the value against other numbers, perhaps with the parseFloat()
function:
function calculateTip(cost) {
if (!parseFloat(cost)) {
throw new Error('Unsupported input.');
}
That way anything that cannot be coerced the an integer (e.g. {}
) will cause the error to be thrown.
Updated code
See the code below with the advice above implemented.
var bills = [124, 48, 268];
var totals = ;
var pointlessArray = ;
function calculateTip(cost) {
if (!parseFloat(cost)) {
throw new Error('Unsupported input.');
}
if (cost < 50) {
return cost * .2;
}
if (cost <= 200) {
return cost * .15;
}
return cost * .1;
}
function makePointlessArray(inputArray) {
var length = inputArray.length;
for (var i = 0; i < length; i++) {
pointlessArray[i] = calculateTip(inputArray[i]);
}
}
function calculateTotal(billArray) {
var length = billArray.length;
for (var i = 0; i < length; i++) {
totals[i] = billArray[i] + calculateTip(billArray[i]);
}
}
makePointlessArray(bills);
calculateTotal(bills);
console.log(`The bills are: ${bills}`);
console.log(`The calculated tips are: ${pointlessArray}`);
console.log(`The calculated totals are: ${totals}`);
break
statements after return
While it is a great habit to include the break
statements, there is no need to include break
statements following a return
, since anything following the return
statement within a function is unreachable.
switch(true)
while this works because each case
statement must evaluate to true, it is simpler to just use if
statements. Your logic checks if the value is less than 50, then if it is greater than 49 and less than 201. The requirements never specified if the values would be integers, floats, etc. So it would be wise to consider a value like 49.5. That value would be less than 50 so the first condition would be true. However if the value was $200.50 the second condition would evaluate to true, even though the value was more than 200. So update the condition to cost <= 200
. Otherwise if neither of those conditions have been met, the value must be more than 200.
function calculateTip(cost) {
if (cost < 50) {
return cost * .2;
}
if (cost <= 200) {
return cost * .15;
}
return cost * .1;
}
Error
The default case of the switch statement merely calls Error
default:
Error('Unsupported input.');
This likely won't do what you expect. If you want an error to be thrown, then instantiate an error with the new
operator and precede it with the throw
operator:
throw new Error('Unsupported input.');
It would be wise the check the input before comparing the value against other numbers, perhaps with the parseFloat()
function:
function calculateTip(cost) {
if (!parseFloat(cost)) {
throw new Error('Unsupported input.');
}
That way anything that cannot be coerced the an integer (e.g. {}
) will cause the error to be thrown.
Updated code
See the code below with the advice above implemented.
var bills = [124, 48, 268];
var totals = ;
var pointlessArray = ;
function calculateTip(cost) {
if (!parseFloat(cost)) {
throw new Error('Unsupported input.');
}
if (cost < 50) {
return cost * .2;
}
if (cost <= 200) {
return cost * .15;
}
return cost * .1;
}
function makePointlessArray(inputArray) {
var length = inputArray.length;
for (var i = 0; i < length; i++) {
pointlessArray[i] = calculateTip(inputArray[i]);
}
}
function calculateTotal(billArray) {
var length = billArray.length;
for (var i = 0; i < length; i++) {
totals[i] = billArray[i] + calculateTip(billArray[i]);
}
}
makePointlessArray(bills);
calculateTotal(bills);
console.log(`The bills are: ${bills}`);
console.log(`The calculated tips are: ${pointlessArray}`);
console.log(`The calculated totals are: ${totals}`);
var bills = [124, 48, 268];
var totals = ;
var pointlessArray = ;
function calculateTip(cost) {
if (!parseFloat(cost)) {
throw new Error('Unsupported input.');
}
if (cost < 50) {
return cost * .2;
}
if (cost <= 200) {
return cost * .15;
}
return cost * .1;
}
function makePointlessArray(inputArray) {
var length = inputArray.length;
for (var i = 0; i < length; i++) {
pointlessArray[i] = calculateTip(inputArray[i]);
}
}
function calculateTotal(billArray) {
var length = billArray.length;
for (var i = 0; i < length; i++) {
totals[i] = billArray[i] + calculateTip(billArray[i]);
}
}
makePointlessArray(bills);
calculateTotal(bills);
console.log(`The bills are: ${bills}`);
console.log(`The calculated tips are: ${pointlessArray}`);
console.log(`The calculated totals are: ${totals}`);
var bills = [124, 48, 268];
var totals = ;
var pointlessArray = ;
function calculateTip(cost) {
if (!parseFloat(cost)) {
throw new Error('Unsupported input.');
}
if (cost < 50) {
return cost * .2;
}
if (cost <= 200) {
return cost * .15;
}
return cost * .1;
}
function makePointlessArray(inputArray) {
var length = inputArray.length;
for (var i = 0; i < length; i++) {
pointlessArray[i] = calculateTip(inputArray[i]);
}
}
function calculateTotal(billArray) {
var length = billArray.length;
for (var i = 0; i < length; i++) {
totals[i] = billArray[i] + calculateTip(billArray[i]);
}
}
makePointlessArray(bills);
calculateTotal(bills);
console.log(`The bills are: ${bills}`);
console.log(`The calculated tips are: ${pointlessArray}`);
console.log(`The calculated totals are: ${totals}`);
answered Dec 20 at 18:18
Sᴀᴍ Onᴇᴌᴀ
8,33261853
8,33261853
1
You forgot that cash money does not exchange in fractions of a cent. Doubles and cash do not mix well.... The OP's questions question is a classic "don't forget to round" trap.
– Blindman67
Dec 22 at 0:16
add a comment |
1
You forgot that cash money does not exchange in fractions of a cent. Doubles and cash do not mix well.... The OP's questions question is a classic "don't forget to round" trap.
– Blindman67
Dec 22 at 0:16
1
1
You forgot that cash money does not exchange in fractions of a cent. Doubles and cash do not mix well.... The OP's questions question is a classic "don't forget to round" trap.
– Blindman67
Dec 22 at 0:16
You forgot that cash money does not exchange in fractions of a cent. Doubles and cash do not mix well.... The OP's questions question is a classic "don't forget to round" trap.
– Blindman67
Dec 22 at 0:16
add a comment |
There's a small bug in your code: a bill of $200.50 will be tipped at the wrong amount since you are testing for cost < 201
.
It's probably easier to just us if
s that are sorted and return the tip from the function on the first one that passes. That avoids the need to test ranges like cost > 49 && cost < 201
. If there were lots of categories you could make a lookup table that would work like this:
const tiptable = [
{min: 200, tip: .1},
{min: 50, tip: .15},
{min: 0, tip: .2}
]
let cost = 51
let tip = tiptable.find(tip => cost > tip.min).tip
console.log(tip)
`find()` will give you the first object that matches. But that only makes sense if there are enough categories that `if` statement get unwieldy.
find()
will give you the first object that matches. But that only makes sense if there are enough categories that if
statement get unwieldy.
Other parts of the code can be simplified with some of the nice functional tools javascript gives us. You can make a one-line sum using reduce()
and you can make an array of tips using map()
allowing you to make the arrays directly without for
loops.
For example:
const bills = [124, 48, 268];
function getTip(cost){
if (cost < 50) return .2
if (cost <= 200) return .15 // not clear whether this should be < or <=
return .1
}
let with_tip = bills.map(cost => cost + cost * getTip(cost) )
let sum = with_tip.reduce((total, n) => total + n)
console.log('Bills with tip: ', with_tip.map(t => t.toLocaleString("en-US", {style: 'currency', currency: 'USD'})))
console.log('Total:', sum.toLocaleString("en-US", {style: 'currency', currency: 'USD'}))
Also, just as an example I added nicely-formatted currency strings with toLocaleString
.
Great answer +1 Would give another +1 for thetiptable
if I could (BTW should betipTable
) and +1 fortoLocaleString
. One tiny problem. What if there are 6 bills of $6.06 each. Your code reports the total as $43.63 which is not a factor of 6, who gets the extra cent? The correct answer is $43.62 with each tip being the same amount. Money values are discrete and you have forgotten to round to nearest cent each time you do a calculation. Always work in whole cents rounding each calculation or you will end up trying to split fractions of a cent.
– Blindman67
Dec 21 at 23:47
Yes, that a great point @Blindman67 and I totally agree about working with whole cents.
– MarkM
Dec 21 at 23:49
It would be wise to disclose that ecmascript-6 features like arrow functions andlet
/const
have certain browser compatibilities to be aware of- while most modern browsers support them, certain users might be using legacy browsers
– Sᴀᴍ Onᴇᴌᴀ
Dec 22 at 0:40
add a comment |
There's a small bug in your code: a bill of $200.50 will be tipped at the wrong amount since you are testing for cost < 201
.
It's probably easier to just us if
s that are sorted and return the tip from the function on the first one that passes. That avoids the need to test ranges like cost > 49 && cost < 201
. If there were lots of categories you could make a lookup table that would work like this:
const tiptable = [
{min: 200, tip: .1},
{min: 50, tip: .15},
{min: 0, tip: .2}
]
let cost = 51
let tip = tiptable.find(tip => cost > tip.min).tip
console.log(tip)
`find()` will give you the first object that matches. But that only makes sense if there are enough categories that `if` statement get unwieldy.
find()
will give you the first object that matches. But that only makes sense if there are enough categories that if
statement get unwieldy.
Other parts of the code can be simplified with some of the nice functional tools javascript gives us. You can make a one-line sum using reduce()
and you can make an array of tips using map()
allowing you to make the arrays directly without for
loops.
For example:
const bills = [124, 48, 268];
function getTip(cost){
if (cost < 50) return .2
if (cost <= 200) return .15 // not clear whether this should be < or <=
return .1
}
let with_tip = bills.map(cost => cost + cost * getTip(cost) )
let sum = with_tip.reduce((total, n) => total + n)
console.log('Bills with tip: ', with_tip.map(t => t.toLocaleString("en-US", {style: 'currency', currency: 'USD'})))
console.log('Total:', sum.toLocaleString("en-US", {style: 'currency', currency: 'USD'}))
Also, just as an example I added nicely-formatted currency strings with toLocaleString
.
Great answer +1 Would give another +1 for thetiptable
if I could (BTW should betipTable
) and +1 fortoLocaleString
. One tiny problem. What if there are 6 bills of $6.06 each. Your code reports the total as $43.63 which is not a factor of 6, who gets the extra cent? The correct answer is $43.62 with each tip being the same amount. Money values are discrete and you have forgotten to round to nearest cent each time you do a calculation. Always work in whole cents rounding each calculation or you will end up trying to split fractions of a cent.
– Blindman67
Dec 21 at 23:47
Yes, that a great point @Blindman67 and I totally agree about working with whole cents.
– MarkM
Dec 21 at 23:49
It would be wise to disclose that ecmascript-6 features like arrow functions andlet
/const
have certain browser compatibilities to be aware of- while most modern browsers support them, certain users might be using legacy browsers
– Sᴀᴍ Onᴇᴌᴀ
Dec 22 at 0:40
add a comment |
There's a small bug in your code: a bill of $200.50 will be tipped at the wrong amount since you are testing for cost < 201
.
It's probably easier to just us if
s that are sorted and return the tip from the function on the first one that passes. That avoids the need to test ranges like cost > 49 && cost < 201
. If there were lots of categories you could make a lookup table that would work like this:
const tiptable = [
{min: 200, tip: .1},
{min: 50, tip: .15},
{min: 0, tip: .2}
]
let cost = 51
let tip = tiptable.find(tip => cost > tip.min).tip
console.log(tip)
`find()` will give you the first object that matches. But that only makes sense if there are enough categories that `if` statement get unwieldy.
find()
will give you the first object that matches. But that only makes sense if there are enough categories that if
statement get unwieldy.
Other parts of the code can be simplified with some of the nice functional tools javascript gives us. You can make a one-line sum using reduce()
and you can make an array of tips using map()
allowing you to make the arrays directly without for
loops.
For example:
const bills = [124, 48, 268];
function getTip(cost){
if (cost < 50) return .2
if (cost <= 200) return .15 // not clear whether this should be < or <=
return .1
}
let with_tip = bills.map(cost => cost + cost * getTip(cost) )
let sum = with_tip.reduce((total, n) => total + n)
console.log('Bills with tip: ', with_tip.map(t => t.toLocaleString("en-US", {style: 'currency', currency: 'USD'})))
console.log('Total:', sum.toLocaleString("en-US", {style: 'currency', currency: 'USD'}))
Also, just as an example I added nicely-formatted currency strings with toLocaleString
.
There's a small bug in your code: a bill of $200.50 will be tipped at the wrong amount since you are testing for cost < 201
.
It's probably easier to just us if
s that are sorted and return the tip from the function on the first one that passes. That avoids the need to test ranges like cost > 49 && cost < 201
. If there were lots of categories you could make a lookup table that would work like this:
const tiptable = [
{min: 200, tip: .1},
{min: 50, tip: .15},
{min: 0, tip: .2}
]
let cost = 51
let tip = tiptable.find(tip => cost > tip.min).tip
console.log(tip)
`find()` will give you the first object that matches. But that only makes sense if there are enough categories that `if` statement get unwieldy.
find()
will give you the first object that matches. But that only makes sense if there are enough categories that if
statement get unwieldy.
Other parts of the code can be simplified with some of the nice functional tools javascript gives us. You can make a one-line sum using reduce()
and you can make an array of tips using map()
allowing you to make the arrays directly without for
loops.
For example:
const bills = [124, 48, 268];
function getTip(cost){
if (cost < 50) return .2
if (cost <= 200) return .15 // not clear whether this should be < or <=
return .1
}
let with_tip = bills.map(cost => cost + cost * getTip(cost) )
let sum = with_tip.reduce((total, n) => total + n)
console.log('Bills with tip: ', with_tip.map(t => t.toLocaleString("en-US", {style: 'currency', currency: 'USD'})))
console.log('Total:', sum.toLocaleString("en-US", {style: 'currency', currency: 'USD'}))
Also, just as an example I added nicely-formatted currency strings with toLocaleString
.
const tiptable = [
{min: 200, tip: .1},
{min: 50, tip: .15},
{min: 0, tip: .2}
]
let cost = 51
let tip = tiptable.find(tip => cost > tip.min).tip
console.log(tip)
`find()` will give you the first object that matches. But that only makes sense if there are enough categories that `if` statement get unwieldy.
const tiptable = [
{min: 200, tip: .1},
{min: 50, tip: .15},
{min: 0, tip: .2}
]
let cost = 51
let tip = tiptable.find(tip => cost > tip.min).tip
console.log(tip)
`find()` will give you the first object that matches. But that only makes sense if there are enough categories that `if` statement get unwieldy.
const bills = [124, 48, 268];
function getTip(cost){
if (cost < 50) return .2
if (cost <= 200) return .15 // not clear whether this should be < or <=
return .1
}
let with_tip = bills.map(cost => cost + cost * getTip(cost) )
let sum = with_tip.reduce((total, n) => total + n)
console.log('Bills with tip: ', with_tip.map(t => t.toLocaleString("en-US", {style: 'currency', currency: 'USD'})))
console.log('Total:', sum.toLocaleString("en-US", {style: 'currency', currency: 'USD'}))
const bills = [124, 48, 268];
function getTip(cost){
if (cost < 50) return .2
if (cost <= 200) return .15 // not clear whether this should be < or <=
return .1
}
let with_tip = bills.map(cost => cost + cost * getTip(cost) )
let sum = with_tip.reduce((total, n) => total + n)
console.log('Bills with tip: ', with_tip.map(t => t.toLocaleString("en-US", {style: 'currency', currency: 'USD'})))
console.log('Total:', sum.toLocaleString("en-US", {style: 'currency', currency: 'USD'}))
answered Dec 20 at 18:59
MarkM
1786
1786
Great answer +1 Would give another +1 for thetiptable
if I could (BTW should betipTable
) and +1 fortoLocaleString
. One tiny problem. What if there are 6 bills of $6.06 each. Your code reports the total as $43.63 which is not a factor of 6, who gets the extra cent? The correct answer is $43.62 with each tip being the same amount. Money values are discrete and you have forgotten to round to nearest cent each time you do a calculation. Always work in whole cents rounding each calculation or you will end up trying to split fractions of a cent.
– Blindman67
Dec 21 at 23:47
Yes, that a great point @Blindman67 and I totally agree about working with whole cents.
– MarkM
Dec 21 at 23:49
It would be wise to disclose that ecmascript-6 features like arrow functions andlet
/const
have certain browser compatibilities to be aware of- while most modern browsers support them, certain users might be using legacy browsers
– Sᴀᴍ Onᴇᴌᴀ
Dec 22 at 0:40
add a comment |
Great answer +1 Would give another +1 for thetiptable
if I could (BTW should betipTable
) and +1 fortoLocaleString
. One tiny problem. What if there are 6 bills of $6.06 each. Your code reports the total as $43.63 which is not a factor of 6, who gets the extra cent? The correct answer is $43.62 with each tip being the same amount. Money values are discrete and you have forgotten to round to nearest cent each time you do a calculation. Always work in whole cents rounding each calculation or you will end up trying to split fractions of a cent.
– Blindman67
Dec 21 at 23:47
Yes, that a great point @Blindman67 and I totally agree about working with whole cents.
– MarkM
Dec 21 at 23:49
It would be wise to disclose that ecmascript-6 features like arrow functions andlet
/const
have certain browser compatibilities to be aware of- while most modern browsers support them, certain users might be using legacy browsers
– Sᴀᴍ Onᴇᴌᴀ
Dec 22 at 0:40
Great answer +1 Would give another +1 for the
tiptable
if I could (BTW should be tipTable
) and +1 for toLocaleString
. One tiny problem. What if there are 6 bills of $6.06 each. Your code reports the total as $43.63 which is not a factor of 6, who gets the extra cent? The correct answer is $43.62 with each tip being the same amount. Money values are discrete and you have forgotten to round to nearest cent each time you do a calculation. Always work in whole cents rounding each calculation or you will end up trying to split fractions of a cent.– Blindman67
Dec 21 at 23:47
Great answer +1 Would give another +1 for the
tiptable
if I could (BTW should be tipTable
) and +1 for toLocaleString
. One tiny problem. What if there are 6 bills of $6.06 each. Your code reports the total as $43.63 which is not a factor of 6, who gets the extra cent? The correct answer is $43.62 with each tip being the same amount. Money values are discrete and you have forgotten to round to nearest cent each time you do a calculation. Always work in whole cents rounding each calculation or you will end up trying to split fractions of a cent.– Blindman67
Dec 21 at 23:47
Yes, that a great point @Blindman67 and I totally agree about working with whole cents.
– MarkM
Dec 21 at 23:49
Yes, that a great point @Blindman67 and I totally agree about working with whole cents.
– MarkM
Dec 21 at 23:49
It would be wise to disclose that ecmascript-6 features like arrow functions and
let
/const
have certain browser compatibilities to be aware of- while most modern browsers support them, certain users might be using legacy browsers– Sᴀᴍ Onᴇᴌᴀ
Dec 22 at 0:40
It would be wise to disclose that ecmascript-6 features like arrow functions and
let
/const
have certain browser compatibilities to be aware of- while most modern browsers support them, certain users might be using legacy browsers– Sᴀᴍ Onᴇᴌᴀ
Dec 22 at 0:40
add a comment |
Jesse_b is a new contributor. Be nice, and check out our Code of Conduct.
Jesse_b is a new contributor. Be nice, and check out our Code of Conduct.
Jesse_b is a new contributor. Be nice, and check out our Code of Conduct.
Jesse_b is a new contributor. Be nice, and check out our Code of Conduct.
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f210059%2fcalculating-tips%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
So the waiter gets more money if the bill is $49 than if it’s $51? Weird... :)
– Cris Luengo
Dec 20 at 22:04