chriswarbo-net: bb77dbdc762b98fa59bf7d9cbebc397467637280

     1: ---
     2: title: Problems with Subtraction
     3: packages: [ 'mathml' ]
     4: ---
     5: 
     6: <small>Part of [my units pages](/projects/units)</small>
     7: 
     8: Subtraction is the operation of "taking away", and acts like the "opposite" of
     9: addition. For example, we can use a subtraction to "undo" an addition:
    10: 
    11: ```{.unwrap pipe="sh | math block minus"}
    12: {
    13:   {
    14:     { var 'x'; var 'y'; } | add
    15:     var 'y'
    16:   } | mapply 'minus'
    17:   var 'x'
    18: } | mapply 'eq'
    19: ```
    20: 
    21: This is a fine idea, but unfortunately subtraction is not as well-behaved as
    22: addition, and I personally think it causes more problems than it solves.
    23: 
    24: ## Subtraction is *redundant* ##
    25: 
    26: We can define subtraction using addition and negation (using
    27: [overbar notation for negatives](negative_bar_notation.html)):
    28: 
    29: ```{.unwrap pipe="sh | math block"}
    30: {
    31:   { var 'x'; var 'y';       } | mapply 'minus'
    32:   { var 'x'; var 'y' | neg; } | add
    33: } | mapply 'equivalent'
    34: ```
    35: 
    36: ```{pipe="sh > neg_answer.mml"}
    37: {
    38:   { num '5'; num '7'; } | mapply 'minus'
    39:   num '2' | neg
    40: } | mapply 'eq'
    41: ```
    42: 
    43: Hence situations involving negatives don't need subtraction: we can stick to
    44: additions, and sprinkle in some negatives as needed. Furthermore, if a situation
    45: *doesn't* allow negatives, then it doesn't allow subtraction either, since
    46: subtraction gives negative answers when the second value is larger than the
    47: first (e.g. `cat neg_answer.mml`{.unwrap pipe="sh | math"}).
    48: 
    49: So any time we might want subtraction, we could add negatives instead; and any
    50: time we can't use negatives, we also can't use subtraction. Thus subtraction
    51: isn't *needed*. We might find it *useful*, but it's ultimately just an
    52: abbreviation for adding negatives.
    53: 
    54: ### Adding negatives using negative digits ###
    55: 
    56: We can use the familiar "long addition" algorithm to add negatives, if we think
    57: of them as having [negative digits](negative_digits.html)!
    58: 
    59: ## Subtraction is *hard* ##
    60: 
    61: We've seen that subtraction is the same as adding negatives, but that doesn't
    62: tell us whether one is "better" than the other. Now I'll show that adding is
    63: preferable, since it follows many nice rules/patterns that subtraction doesn't;
    64: hence making it easier to add negatives (both mentally, and on a computer)!
    65: 
    66: ### Subtraction doesn't commute ###
    67: 
    68: ```{pipe="sh > add_comm.mml"}
    69: {
    70:   { var 'x'; var 'y'; } | add
    71:   { var 'y'; var 'x'; } | add
    72: } | mapply 'eq'
    73: ```
    74: 
    75: ```{pipe="sh > not_comm.mml"}
    76: {
    77:   { var 'x'; var 'y'; } | mapply 'minus'
    78:   { var 'y'; var 'x'; } | mapply 'minus'
    79: } | mapply 'neq'
    80: ```
    81: 
    82: ```{pipe="sh > anti_comm.mml"}
    83: {
    84:   { var 'x'; var 'y'; } | mapply 'minus'
    85:   { var 'y'; var 'x'; } | mapply 'minus' | neg
    86: } | mapply 'eq'
    87: ```
    88: 
    89: We can swap around the values of an addition without changing the result: we say
    90: addition *commutes*, i.e. that `cat add_comm.mml`{.unwrap pipe="sh | math"}.
    91: 
    92: In contrast, we *can't* swap around the values of a subtraction, since
    93: `cat not_comm.mml`{.unwrap pipe="sh | math"}. In fact, doing so will negate the
    94: result: `cat anti_comm.mml`{.unwrap pipe="sh | math"} (we say that subtraction
    95: "anti-commutes").
    96: 
    97: ### Subtraction doesn't associate ###
    98: 
    99: ```{pipe="cat > add_left.mml"}
   100: <mrow>
   101:   <mrow>
   102:     <mo>(</mo>
   103:     <mi>x</mi>
   104:     <mo>+</mo>
   105:     <mi>y</mi>
   106:     <mo>)</mo>
   107:   </mrow>
   108:   <mo>+</mo>
   109:   <mi>z</mi>
   110: </mrow>
   111: ```
   112: 
   113: ```{pipe="cat > add_right.mml"}
   114: <mrow>
   115:   <mi>x</mi>
   116:   <mo>+</mo>
   117:   <mrow>
   118:     <mo>(</mo>
   119:     <mi>y</mi>
   120:     <mo>+</mo>
   121:     <mi>z</mi>
   122:     <mo>)</mo>
   123:   </mrow>
   124: </mrow>
   125: ```
   126: 
   127: ```{pipe="sh > add_flat.mml"}
   128: { var 'x'; var 'y'; var 'z'; } | add
   129: ```
   130: 
   131: Addition extends to arbitrarily-many inputs, which we call being "associative".
   132: In particular, `cat add_left.mml`{.unwrap pipe="sh | math nosem"} is the same as
   133: `cat add_right.mml`{.unwrap pipe="sh | math nosem"}, so we can just avoid
   134: nesting altogether and write `cat add_flat.mml`{.unwrap pipe="sh | math"} (the
   135: same goes when dealing with more than three inputs, nested in any way).
   136: 
   137: ```{pipe="sh > sub_neq.mml"}
   138: {
   139:   {
   140:     { var 'x'; var 'y'; } | mapply 'minus'
   141:     var 'z'
   142:   } | mapply 'minus'
   143:   {
   144:     var 'x'
   145:     { var 'y'; var 'z'; } | mapply 'minus'
   146:   } | mapply 'minus'
   147: } | mapply 'neq'
   148: ```
   149: 
   150: ```{pipe="sh > sub_left_example.mml"}
   151: {
   152:   {
   153:     { num '1'; num '2'; } | mapply 'minus'
   154:     num '3'
   155:   } | mapply 'minus'
   156:   {
   157:     num '1' | neg
   158:     num '3'
   159:   } | mapply 'minus'
   160:   num '4' | neg
   161: } | mapply 'eq'
   162: ```
   163: 
   164: ```{pipe="sh > sub_right_example.mml"}
   165: {
   166:   {
   167:     num '1'
   168:     { num '2'; num '3'; } | mapply 'minus'
   169:   } | mapply 'minus'
   170:   {
   171:     num '1'
   172:     num '1' | neg
   173:   } | mapply 'minus'
   174:   num '2'
   175: } | mapply 'eq'
   176: ```
   177: 
   178: ```{pipe="cat > sub_flat_example.mml"}
   179: <mrow>
   180:   <mn>1</mn>
   181:   <mo>-</mo>
   182:   <mn>2</mn>
   183:   <mo>-</mo>
   184:   <mn>3</mn>
   185: </mrow>
   186: ```
   187: 
   188: In contrast, using subtraction with more than two values is ambiguous. For
   189: example `cat sub_flat_example.mml`{.unwrap pipe="sh | math nosem"}
   190: could mean `cat sub_left_example.mml`{.unwrap pipe="sh | math"} *or* it could
   191: mean `cat sub_right_example.mml`{.unwrap pipe="sh | math"}, which give different
   192: results. In general `cat sub_neq.mml`{.unwrap pipe="sh | math"}, so we're forced
   193: to keep careful track of nesting when using subtraction.
   194: 
   195: ```{pipe="sh > add_example_flat.mml"}
   196: { var 'a'; var 'b'; var 'c'; var 'd'; var 'e'; var 'f'; } | add
   197: ```
   198: 
   199: ```{pipe="cat > add_example_nest.mml"}
   200: <mrow>
   201:   <mrow>
   202:     <mo>(</mo><mi>a</mi><mo>+</mo><mi>b</mi><mo>)</mo>
   203:   </mrow>
   204:   <mo>+</mo>
   205:   <mrow>
   206:     <mo>(</mo><mi>c</mi><mo>+</mo><mi>d</mi><mo>)</mo>
   207:   </mrow>
   208:   <mo>+</mo>
   209:   <mrow>
   210:     <mo>(</mo><mi>e</mi><mo>+</mo><mi>f</mi><mo>)</mo>
   211:   </mrow>
   212: </mrow>
   213: ```
   214: 
   215: Associative operations are also better for computers, since they're trivial to
   216: calculate in parallel. For example, if we have three processors, we can
   217: calculate `cat add_example_flat.mml`{.unwrap pipe="sh | math"} in parallel by
   218: transforming it into `cat add_example_nest.mml`{.unwrap pipe="sh | math nosem"};
   219: the result will always be identical, but the nested parts can be calculated
   220: independently, and hence on separate processors at the same time. We cannot
   221: perform such transformations for operations that *aren't* associative; hence
   222: subtraction can't easily be done in parallel.

Generated by git2html.