1

How do you handle the following scenario without null?

You have this problem (In Java):

BigDecimal sales = ...;
BigDecimal cost = ...;
BigDecimal profit = sales.subtract(cost);
// Profit Margin = profit / sales
BigDecimal profitMargin = profit.divide(sales, 20, RoundingMode.HALF_UP);

Because sales is sometimes zero, we turn the last line into:

BigDecimal profitMargin = sales.compareTo(BigDecimal.ZERO) == 0 ? null : profit.divide(sales, 20, RoundingMode.HALF_UP);

In which case if profitMargin == null, then we know what that means. If you make profitMargin = 0, that isn't really correct, nor is infinity a good value either. It seems best that it would remain undefined. Yet, it is an "unexploded bomb." So, what's the best way to handle this?

This questions as originally asked on Stack Overflow, and also referred me to the question Are null references really a bad thing?

ryvantage
  • 119
  • 1
  • 4
  • 1
    This is a math question essentially. How much is 20% of 0? 0. What's wrong with that response? – littleadv Jun 21 '14 at 05:55
  • Do you intend to use this value in some kind of weighted-average formula? If so, check to see how that formula handles items that has a zero divisor (i.e. when sales is zero). Note that common "textbook formulas" may neglect to handle the division-by-zero case; you might want to take the business textbook definition and ask a math tutor to "reformulate" it instead. – rwong Jun 21 '14 at 08:40
  • 6
    I think you are asking the wrong people. This is a business domain problem, and the best people to answer it are your own users. From my experience, this should be a % and there is no consensus; some users will say you should return 20%, others will say zero. – andy256 Jun 21 '14 at 08:43
  • Agreeing with @andy256; to give an example, a weighted average of three values may be given by `(W1*A1 + W2*A2 + W3*A3) / (W1 + W2 + W3)`, which is valid if at least one of `W1, W2, W3` is nonzero. If an item has zero weight (let's say W1 == 0), the item's value (A1) gives no contribution to the mix (i.e. has no bearing on the result). This is the reason for asking to go back to the business textbook formula and to truly understand what it meant. (Usually, the original formula would handle divisions-by-zero but the "step-by-step calculations" would not.) – rwong Jun 21 '14 at 15:30
  • 1
    I'm voting to close this question as off-topic because this is a business/domain question. Basically, you need to take this question to your stakeholders -- presumably your accounting department, in this case... – svidgen Jan 11 '18 at 16:41

4 Answers4

9

If sales are zero, profit margin is zero.

Zero is a perfectly good result to substitute for the undefined result of a divide by zero calculation in many cases, and it avoids the use of null unless you specifically want to know about the zero sales case.

Robert Harvey
  • 198,589
  • 55
  • 464
  • 673
  • Why zero? Why not add a small buffer value (say 0.0001) to the denominator to get a large number? If a company makes no sales and makes profit I would argue that should be a "high" profit margin rather than a 0 profit margin, as compared to other companies... – Psi Sep 20 '19 at 12:26
7

Don't ask Us! We're not the ones making business decisions based on the output of your calculations!

Having said that, developers need to know how to approach these situations. In my experience, dilemmas like this fall into two broad scenarios:

  1. This happens relatively often and business users will see output based on $0.00 sales on a regular basis.

  2. This is a corner case that happens extremely rarely. It is so infrequent that business users have difficulty remembering the "last time" it happened. When it does happen, its not a business crisis.

For scenario #1, I would go to the business users and ask them what profit margin % they want to see for $0.00 sales.

For scenario #2, this probably isn't worth wasting the time of business users to find out what they want to see. I would set it to something that is least likely to give a false impression, probably 0%. In my opinion using a number like 20% would give the false impression that money is being made. Don't make a decision on your own unless you are familiar with the users and business. When in doubt, consult the business users.

poke
  • 570
  • 4
  • 12
2

My question is: how do you handle the following scenario without null?

The way you would handle it on a balance sheet (i.e. it's 0).

Maths is a bad example for nulls. Maths has worked without nulls for centuries, and there is never a balance sheet or a general ledger or a kid's maths homework book that says "null".

Programming had the problem of what to assign to a variable for which memory was not yet allocated, and that's where null was born. Perhaps you need to find another example for null (and you'll find many), but definitely not maths :-)

Omer Iqbal
  • 3,224
  • 15
  • 22
  • Can you link an example of a balance sheet that shows 0 for the margin rather than "-" or "na"? – Psi Sep 20 '19 at 12:24
1

@Robert answer requires that you can use a profit margin of 0 if sales are 0, or have the ability at later times to access sales to test if they are 0 before using profit margin. If this is the case, then his answer is acceptable.

If however you need to know if the profit margin is 'NaN' at some future processing stage, another approach would be to extend BigDecimal so the fact that sales was 0 when trying to calculate it is preserved.

It would be my preferred approach to extend BigDecimal and create a new class for Profit Margin regardless, as the improved type correctness makes programs easier to understand and maintain.

mattnz
  • 21,315
  • 5
  • 54
  • 83