Front-End and Back-End calculating different amounts? Should the calculation be done in the same place? - frontend

So I have this issue with a website that I work on.
It goes like so (note: This is not exactly what happens. I am just painting a picture):
Front-End:
User has a cart full of things they want to buy
Front-End calculates the amount that should be paid (this calculates in discounts, sales, Buy One Get One, etc.)
User submits and pays the amount
Back-End:
Items are bought and money is received
Backend calculates a different amount for what everything should have cost
Backend wants either less or more money
I think that I should calculate the amount in the same place. I think in step 2 I could make a call to the backend to determine what the amount should be.
That way I wouldn't run into this issue where they are calculating 2 different amounts. What do you guys think?

If your frontend is implemented in JavaScript or some language that transcribes to JavaScript you should keep any business critical calculations (such as payment amounts) away from there. JavaScript logic is easy to manipulate in the browser and all critical code therefore needs to be executed in the backend server.
You should do exactly as you are suggesting and call your backend in step 2.
This will also make the system easier to maintain as you won't have duplicated logic in two places, any refactoring or debugging regarding this logic can be done in a single location in the codebase.

This is probably a problem with rounding and floating numbers. The rounding functions and systems representing the numbers can be differently defined when different programming languages are used. Either you can use a library to use decimal numbers or try to implement the rounding behavior for one side to match the other side. Then it is always advised to calculate with integers as much as possible. Multiplying with 100 at the beginning and dividing with 100 at the end of calculations help to stabilize the numbers. Also, you should consider using bankers round also called Half Even rounding as a strategy when rounding currencies to minimize the total failure.
For TypeScript the function could be:
function roundHalfEven(x: number, d: number) {
const p = Math.pow(10, d);
const xp = x * p;
const r = Math.round(xp);
return (Math.abs(xp) % 1 == 0.5 && r % 2 != 0 ? r - 1 : r) / p;
}
The line const xp = x * p; could also be made more stable with const xp = parseFloat((x * p).toPrecision(15)).
But also do never trust anything coming from the browser. So you should definitely check at the end on your server if everything adds up.
You can find more information on rounding and how to handle failures on the following pages:
Good answer on this topic but be aware that everything should be taken with a grain of salt. For example the solution to Math.round(-0.5) is -0 and not -1 as in Amr Alis response.
ICU on rounding The most important rounding methods with sample data.

Related

How to check internal size parameters that controls example generation

In PropEr, there's an internal variable called Size that represents the size of generated example.
For instance, when we have 2 variables and would like to make them proportional each other, PropEr let you write the following test:
prop_profile2() ->
?FORALL(Profile, [{name, string()},
{age, pos_integer()},
{bio, ?SIZED(Size, resize(Size*35, string()))}],
begin
NameLen = to_range(10, length(proplists:get_value(name, Profile))),
BioLen = to_range(300, length(proplists:get_value(bio, Profile))),
aggregate([{name, NameLen}, {bio, BioLen}], true)
end).
In this test, the internal variable Size holds the internal size of string() (string value generator), so what ?SIZED(Size, resize(Size*35, string())) does here is make this part 35 times larger than string() called next to name atom.
I tried to something similar to this with Hypothesis, but what I could come up with was the following:
#composite
def profiles(draw: DrawFn):
name = draw(text(max_size=10))
name_len = len(name)
age = draw(integers(min_value=1, max_value=150))
bio_len = 35 * name_len
bio = draw(text(min_size=bio_len, max_size=bio_len))
return Profile(name, age, bio)
Are there any other smarter ways to have proportional sizes among multiple variables?
If the code you're testing actually requires these proportions, your test looks good, though I think a direct translation of your PropEr code would have bio = draw(text(min_size=bio_len, max_size=max(bio_len, 300)))? As-is, you'd never be able to find bugs with even-length bios, or short bios, and so on.
This points to a more fundamental question: why do you want proportional inputs in the first place?
Hypothesis style is to just express the limits of your allowed input directly - "builds(name=text(max_size=10), age=integers(1, 150), bio=text(max_size=300))` - and let the framework give you diverse and error-inducing inputs from whatever weird edge case it finds. (note: if you're checking the distribution, do so over 10,000+ examples - each run of 100 won't look very diverse)
PropEr style often adds further constraints on the inputs, in order to produce more realistic data or guide generation to particular areas of interest. I think this is a mistake: my goal is not to generate realistic data, it's to maximize the probability that I find a bug - ignoring part of the input space can only hurt - and then to minimize the expected time to do so (a topic too large for this answer).

partial functions vs input verification

I really love using total functions. That said, sometimes I'm not sure what the best approach is for guaranteeing that. Lets say that I'm writing a function similar to chunksOf from the split package, where I want to split up a list into sublists of a given size. Now I'd really rather say that the input for sublist size needs to be a positive int (so excluding 0). As I see it I have several options:
1) all-out: make a newtype for PositiveInt, hide the constructor, and only expose safe functions for creating a PositiveInt (perhaps returning a Maybe or some union of Positive | Negative | Zero or what have you). This seems like it could be a huge hassle.
2) what the split package does: just return an infinite list of size-0 sublists if the size <= 0. This seems like you risk bugs not getting caught, and worse: those bugs just infinitely hanging your program with no indication of what went wrong.
3) what most other languages do: error when the input is <= 0. I really prefer total functions though...
4) return an Either or Maybe to cover the case that the input might have been <= 0. Similar to #1, it seems like using this could just be a hassle.
This seems similar to this post, but this has more to do with error conditions than just being as precise about types as possible. I'm looking for thoughts on how to decide what the best approach for a case like this is. I'm probably most inclined towards doing #1, and just dealing with the added overhead, but I'm concerned that I'll be kicking myself down the road. Is this a decision that needs to be made on a case-by-case basis, or is there a general strategy that consistently works best?

Dynamic Programming algorithm shortest path between two

There's an algorithm currently driving me crazy.
I've seen quite a few variations of it, so I'll just try to explain the easiest one I can think about.
Let's say I have a project P:
Project P is made up of 4 sub projects.
I can solve each of those 4 in two separate ways, and each of those modes has a specific cost and a specific time requirement:
For example (making it up):
P: 1 + 2 + 3 + 4 + .... n
A(T/C) Ta1/Ca1 Ta2/Ca2 etc
B(T/C) Tb1/Cb1 etc
Basically I have to find the combination that of those four modes which has the lowest cost. And that's kind of easy, the problem is: the combination has to be lower than specific given time.
In order to find the lowest combination I can easily write something like:
for i = 1 to n
aa[i] = min(aa[i-1],ba[i-1]) + value(a[i])
bb[i] = min(bb[i-1],ab[i-1]) + value(b[i])
ba[i] = min(bb[i-1],ab[i-1]) + value(b[i])
ab[i] = min(aa[i-1],ba[i-1]) + value(a[i])
Now something like is really easy and returns the correct value every time, the lowest at the last circle is gonna be the correct one.
Problem is: if min returns modality that takes the last time, in the end I'll have the fastest procedure no matter the cost.
If if min returns the lowest cost, I'll have the cheapest project no matter the amount of time taken to realize it.
However I need to take both into consideration: I can do it easily with a recursive function with O(2^n) but I can't seem to find a solution with dynamic programming.
Can anyone help me?
If there are really just four projects, you should go with the exponential-time solution. There are only 16 different cases, and the code will be short and easy to verify!
Anyway, the I'm pretty sure the problem you describe is the knapsack problem, which is NP-hard. So, there will be no exact solution that's sub-exponential unless P=NP. However, depending on what "n" actually is (is it 4 in your case? or the values of the time and cost?) there may be a pseudo-polynomial time solution. The Wikipedia article contains descriptions of these.

Discontinuity in results from Excel's Present Value function PV

The PV function of Excel (present value of an investment) seems to make a sudden jump somewhere and is raising an error. For example:
WorksheetFunction.PV(-19, 240, 500000)
will return a value while:
WorksheetFunction.PV(-20, 240, 500000)
will raise an exception. There are other examples where things go wrong. Independently of the semantic meaning of the parameters, the formula to calculate the PV is purely continuous around the jump, so what is causing this?
When calculating things in, for instance, Mathematica this does not happen.
The first term of the formula used to calculate PV is PV * (1+rate) ^ nper (as in your link). Using your first example this gives 4.84861419016704E+304 so close enough to Excel’s limit (of 9.99999999999999E+307) that no element of the first term would have to increase by much for the result to exceed the inbuilt limitation, for which your second example seems to have been enough.
Note that, as #Juliusz has pointed out, the first parameter is the interest rate per period and 19 represents 1900%. For 240 periods (looks like 20 years) the combination is not realistic (ie 1900% per month). Also, the rate should not normally be negative (better to handle whether in or out by signing the payment amount).
Seems that -19.45 is the minimum value, which translates to -1945%. Are you sure you need more?

Moore’s Law Problem [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 9 years ago.
Improve this question
Suppose you need to run a program on the world’s fastest supercomputer which will take 10 years to complete. You could:
Spend $250M now
Program for 9 years, Moore’s law speedup (4,000x faster), spend $1M in 10years, complete in 2 weeks.
What is the optimum strategy?
Question from "Long Term Storage Trends and You"
Moore's Law is not about speed, it's about the number of transistors in a given area of silicon. There is no guarantee that in 9 years the speed will increase 4000x. If anything, GHz speed has levelled off in recent years. What is increasing, currently, is the number of cores in a CPU.
In your question, if the program does not lend itself to vectorisation (i.e. can be split into distinct parts that can be computed in parallel) then waiting 9 years will not provide any benefit, it won't be that much faster as clock speeds are unlikely to raise much in the intervening years.
Assuming the program is infinitely parallelizable (so it can always take advantage of all cores of all CPUs available)...
Assuming the program cannot be paused and moved to a different machine in mid-run...
Assuming time is the only issue (maybe we have a big research grant and we always use the best computers available)...
We have four equations (well, actually two of them are functions):
endtime(startyear) = startyear + (calculations / speed(startyear))
speed(year) = speed(year-1.5)4 (the problem assumes both hardware and software double in speed every 18 months)
endtime(0) = 0 + (calculations/speed(0)) = 10 years
speed(0) = calculations/(10 years) (implied by #3)
I started to use derivatives to minimize endtime, but I realized I can't remember my differential equations very well. So I transformed #2 into the equivalent exponential-growth formula:
speed(year) = speed(0)*4(year/1.5) = (calculations/10)*4(year/1.5)
Then I wrote this little BeanShell script:
calculations() {
return 10000000; // random constant (gets cancelled out anyway)
}
speed(year) {
speed0 = calculations()/10; // constant factor
return speed0*Math.pow(4.0, year/1.5);
}
endtime(startyear) {
return startyear + calculations()/speed(startyear);
}
findmin() {
start = 0.0;
finish = 10.0;
result = 0.0;
// home in on the best solution (there should only be one minimum)
for (inc = 1; inc > 0.00000001; inc /= 2.0) {
result = findmin(start,finish,inc);
start = result-2*inc;
finish = result+inc;
}
print("Minimum value is " + result + ", taking a total of " +
endtime(result) + " years");
}
findmin(start,finish,inc) {
lastNum = 0;
lastVal = Double.MAX_VALUE;
for (i = start; i < finish; i += inc) {
result = endtime(i);
if (result > lastVal) {
print("Minimum value between " + start + " and " + finish +
" is " + lastVal + ", occurring at " + lastNum);
return i;
}
lastNum = i;
lastVal = result;
}
return lastNum;
}
Output:
bsh % source("moore.bsh");
bsh % findmin();
Minimum value between 0.0 and 10.0 is 3.5749013123685915, occurring at 2.0
Minimum value between 1.0 and 4.0 is 3.4921256574801243, occurring at 2.5
Minimum value between 2.0 and 3.5 is 3.4921256574801243, occurring at 2.5
Minimum value between 2.25 and 3.0 is 3.4886233976754246, occurring at 2.375
Minimum value between 2.25 and 2.625 is 3.488620519067143, occurring at 2.4375
Minimum value between 2.375 and 2.5625 is 3.488170701257679, occurring at 2.40625
Minimum value between 2.375 and 2.46875 is 3.488170701257679, occurring at 2.40625
Minimum value between 2.390625 and 2.4375 is 3.488170701257679, occurring at 2.40625
(snip)
Minimum value between 2.406149387359619 and 2.4061494767665863 is 3.4881706965827037,
occurring at 2.4061494171619415
Minimum value is 2.4061494320631027, taking a total of 3.488170696582704 years
So, with the assumptions I stated before, the answer is to wait 2.406149... years (or approximately 2 years, 148 days, according to Google).
Edit: I noticed that with second formula rewritten as above, solving only requires simple calculus.
endtime(x) = x + c/speed(x) (where c = calculations)
speed(x) = speed(0) * 4^(x/1.5) = (c/10)*4^(2x/3)
=> endtime(x) = x + c/((c/10)*4^(2x/3))
= x + 10*(4^(-2x/3))
d/dx endtime(x) = 1 + 10*ln(4)*(-2/3)*(4^(-2x/3))
Critical point is when d/dx = 0, so
1 + 10*ln(4)*(-2/3)*(4^(-2x/3)) = 0
=> 4^(-2x/3) = 1/(10*ln(4)*(2/3))
Take log4 of both sides: (remember that log4(x) = ln(x)/ln(4), and that ln(1/x) = -ln(x))
-2x/3 = ln(1/(10*ln(4)*(2/3))) / ln(4)
= -ln(10*ln(4)*2/3) / ln(4)
=> x = (-3/2) * -ln(1/(10*ln(4)*2/3)) / ln(4)
= 3*ln(10*ln(4)*(2/3)) / 2*ln(4)
That looks like an awful mess (it doesn't help that there's no good way to show math formulas here). But if you plug it into your calculator, you should get 2.4061494159159814141268120293221 (at least if you use the Windows calculator, like I just did). So my previous answer was correct to seven decimal places (which are meaningless in a problem like this, of course).
(I should note that this is just a critical point, not necessarily a minimum. But the second derivative (which is of the form -(some constant)*4-2x/3) is always negative. So the function is always concave up, therefore the only critical point is the minimum.)
Moore's Law is concerned with the number of transistors that will be placed into one single chip and does not relate to the speed of microprocessors in general.
That said, from the current trend we are seeing, we'll probably see more and more cores being fit into a single processor die, so concurrent programming is going to become more and more important to take advantage of the raw processing power available in a processor.
So, it's hard to say whether to do it now or wait -- however, either way, concurrent programming or distributed computing is going to come into play, as we won't be seeing a single core processor becoming exponentially faster (in terms of clock speed) due to the physical limitations of current semiconductor technology and the laws of nature.
Make sure your program can pause and continue, and then put it on faster and faster machines as they come along. Best of both worlds...
Spend the money now - the price/value of the dollar now vs an estimate in 10 years is like trying to forecast weather 3 months from now. Plus this fails to consider factors like programming trends in 10 years and whether things will actually be 4,000 times faster or 4,000 times more scalable/parallel which seems to be the trend of late.
Also, according to the Mayans the world will end in 2012 so spend the loot now!
Simplify the model to make an estimate that you can run now. As more/better resources become available, refine the model for more accurate results.
The fastest way to complete it would be to:
Write a version for current technology that could be migrated to each new generation.
Alongside migrations, continue programming for any improvements algorithmically etc.
The cheapest way would obviously be to leave it for longer. You do need to factor in programming time (which would be near enough constant).
Also, I wouldn't want to stake too much on moore's law continuing.
Also remember that moore's law relates to the density of transistors not to computing speed for a particular problem. Even if computing power in general improves by that much, it doesn't necessarily mean your application will benefit.
But Moore's law does not speed up programming.
9 years of programming will never be condensed into 2 weeks.
Unless you successfully spend the 9 years programming an automated thought reading machine I suppose.
Program for 4 years and then run it in 2.5?
(I'm sure there's a "perfect" answer somwehere between 4 and 5 years...)
The optimum strategy depends on the reason you have to run the program.
In this scenario, the second option is the best one, because the moment you'll have the result (which is what actualy matters) would be the same.
Actually, I believe that if everybody choose the first one (and had the money to do that) ... the Moore's Law would be compromised. I assume that if all our computational needs were satisfied ... we wouldn't be so commited in keep the technology development moving forward.
This makes a flawed assumption that Moore's Law is actually a Law. It would probably be better named Moore's Theory. The risk you run by waiting is that in 10 years, it may still take 10 years to run. Start the program now (with pause and restart built in if possible), start a team looking at other ways to solve the problem that will be faster. Once you have confidence that one or the other will provide a quicker solution, switch.
EDIT: As a problem I think the best value in this question is that it makes you examine whether your assumptions are valid. The obvious solution -- since according to the problem definition you get the same result in the same amount of time with less money -- is to wait, but it depends on some implicit assumptions. If those assumptions don't hold, then the obvious solution is not necessarily the best as many answers here attest.
It's specified in the question that the problem runs on a super-computer, thus the problem must be vectorizable. The speed of of a super-computers is going up vastly faster than Moores law, so depending on the actual problem space one approach would be to hire hacker banditos to create a world wide distributed Warhol Worm that acquired the resources of 85% of the computers on the net for a short massively distributed grid like the Mersenne prime search (GIMPS) and solve the problem in 20 minutes.
(many ways to solve a problem but I sure hope this is labeled as humor)

Resources