Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Re^5: How to write testable command line script?

by pryrt (Abbot)
on Nov 26, 2018 at 15:02 UTC ( [id://1226341]=note: print w/replies, xml ) Need Help??


in reply to Re^4: How to write testable command line script?
in thread How to write testable command line script?

That does not seem right to me. From how I understand it, -60 seconds or -1 minute is NOT the same as -1degree 59minutes. That's like saying, in time math, that subtracting 60 seconds is the same as subtracting 1 hour 59 minutes: really, in h:m:s, -60s = -0:01:00; or, in a similar procedure in decimal math, that's like saying that subtracting 10/100ths from 0 would convert -10/100 to -1/10, and then to carry the negative sign, add 10/10 and subtract 1 unit, which would be -1.90 -- when it should really be -10/100 reduces to -1/10, and then the negative sign carries out to the unit of 0, so -0.10.

Think of it this way, in the final DMS or HMS notations, the DMS/HMS operators are a higher precedence than the unary minus operator -- so -0° 1' 0" is equivalent to -(0° 1' 0") = -(0 + 1/60 + 0/3600) = -(0 + 0/60 + 60/3600) = -60/3600 = -60 seconds

Checking a few online calculators/converters, they seem to agree with me. (I haven't yet found something more authoritative than a calculator... but it matches my reasoning above): If I go to this online DMS converter, and change -0.0167 (which is slightly more negative than -1/60 of a degree, or -1minute), it reads -0° 1' 0.12". And on another online tool, if you start with 0° 0' 0", and subtract 0° 1' 0", you get -0° 1' 0". Can you show a reference where -60seconds is displayed as -1° 59' 0"?

  • Comment on Re^5: How to write testable command line script?

Replies are listed 'Best First'.
Re^6: How to write testable command line script?
by thechartist (Monk) on Nov 26, 2018 at 15:16 UTC

    This is not a degree to decimal converter. This takes angles in deg,min,sec format (all integers) and adds or subtracts them.

    The degree min sec format is a polynomial of the form (10^x)a + (1/60)a + (1/3600)a, if we were going to express this as decimal, where a and x are integers. This is no different from any decimal, which is in powers of 10: (10^2)a + 10b + c + (10^-1)d + (10^-2)e ...; we always simplify decimal numbers by borrowing from the next highest term if subtraction is negative, and carrying excess if addition results in a number greater than equal to the base we are working in.

    The book I cited in my previous post (Trigonometry Refresher by Albert Klaf) describes the procedure on page 12. I would post the link, but I don't believe links make it through correctly. Google books has that page available.

    As for online calculators -- I have found issues with them that are not consistent with what I understand to be the algebraic properties of angle addition and subtraction. Any calculator that does not reduce 60 min to 1 degree by carrying over to the next higher term, is not correct. I will consider your argument and see if I can come up with a proof of my method, or counter-example to yours, later, if the above does not persuade you.

      update: AnomalousMonk said it way better than I did. Original left for historical purposes.


      You've misunderstood. I am claiming you are representing negative angles incorrectly. After the subtraction, if you get -60 seconds, you should have the equivalent of -1min. -1min is represented canonically as -0° 1' 0", not as -1° 59' 0". The answer you list in Re^2: How to write testable command line script? of my $test_7 = [ 0, 0, -60]; my $answer_7 = [-1, 59,  0]; is wrong. Honestly, your format doesn't allow you to use the right answer, unless you know how to get perl to store the "-0" correctly (for example, using text), because it should be my $answer_7 = [-0, 1, 0];.

      regarding normal base-10 subtraction, when you subtract 0.1 from 0.0, you do NOT borrow one from the ones column, making it -1; then have 10 in the tenths column, and subtract 1, leaving 9/10ths, or -1.9. 0.0-0.1 is obviously -0.1. What you are claiming in DMS is exactly equivalent to claiming that -60sec is -1° 59' 0".

       0.0        Try borrowing: (0-1=-1).(0+10=10) => (-1).(10)
      -0.1                                            -( 0).( 1)
      ====                                            ==========
      -0.1                                             (-1).( 9)  => -1.9
      
      That's nonsensical, so obviously not the right method for subtracting a bigger from a smaller.
      
      To subtract a bigger number (M) from a smaller number (S) to do a difference D=M-S, you have to do -(S-M)=D
      So start with the S-M:
       0.1
      -0.0
      ====
       0.1
      Then negate the answer
      -0.1
      
      
      The same is true in other bases, like the base 60 of DMS:
       0°00'00"
      -0°00'60"
      ========
      ??°??'??"
      
      You start by making the bigger the first,
       0°00'60"
      -0°00'00"
      ========
      ????????
      Then simplify the top term and subtract
       0°01'00"
      -0°00'00"
      ========
       0°01'00"
      
      The negate: 
      -0°1'0"
      

      However you calculate it, whether you do it in decimal degrees, or in DMS, the only difference between -60s and +60s should be the sign at the beginning. +60s is (0° 1' 0"), and -60s is -(0° 1' 0"), which gets simplified to -0° 1' 0", exactly like -(0.016) gets simplified to -0.016 -- the negative sign is placed next to the most significant digit, but implies the whole result is negative. -0.016deg converts to -(0.016deg + 0/60 + 0/3600) = -(0 + 1/60 + 0/3600) = -(0° 1' 0"). You do not interpret -0.016 = (-0) + (0/10) + (1/100) + (6/1000) -- because that math evaluates to +16/1000, which is wrong. You evaluate -0.016 as -(0.016) = -(0 + 0/10 + 1/100 + 6/1000) = -(16/1000), which is right; or, in the other direction (-16 thousandths) = -(16 thousandths) = -(1 hundredth + 6 thousandths) = -(zero ones + 0 tenths + 1 hundredths + 6 thousandths). In the same way, -60sec = -(60sec) = -(0 + 0/60 + 60/3600) = -(0 + 1/60 + 0/3600) = -(0° 1' 0") = -0° 1' 0". Negative Degress minutes seconds (-x°y'z") is not (-x°) + (y') + (z") = -x + y/60 + z/3600, it is -(x° + y' + z") -(x + y/60 + z/3600).

      Have I said this in a way that makes my point more clear?

      the resource https://books.google.com/books?id=YRNeBAAAQBAJ&lpg=PR1&dq=Albert%20Klaf's%20Trigonometry%20Refresher&pg=PA12#v=onepage&q&f=false did not show an example when the result is negative. I do not believe you are extending into negative results correctly.

      (and linking works just fine to me: click on the LINK icon once you've navigated to the google books page, copy the URL, and paste it here between square brackets, like [https://books.google.com/books?id=YRNeBAAAQBAJ&lpg=PR1&dq=Albert%20Klaf's%20Trigonometry%20Refresher&pg=PA12#v=onepage&q&f=false].

        I appreciate your input, and I generally agree my representation is not optimal for extension, but I want to clarify what my algorithm does, because this is not a correct understanding of the representation.

        The algorithm is based on complement arithmetic, which is why I didn't give it too much thought. The Japanese soroban is based upon it; ie. When subtracting 2 - 8, you add the complement of 8, in base 10 is 2, because 2+8 = 10. The problem of 2-8 becomes (2+2)-10 = -6. In base 60, we would add the complement of 60 and subtract a 1 from the column on the left, until we get to the degrees, which are in decimal format.

        For the very reasons you outlined (Perl's representation of small negatives), I represent -0.1 as an equivalent polynomial (-1 + 9/10), or in this case 0 -1 0 as (-1 + 59/60 + 0), with the denominator implied as (-1 59 0).

        Algebraically, a + (-a) = 0. If (0 -1 0) + (0 1 0) = (0 0 0), then we must treat -1 59 0 as equivalent to 0 -1 0, because (-1 59 0) + (0 1 0) = (-1 60 0) = (0 0 0).

        Ah. I think I understand now. Thanks for catching my error. I have no idea why I didn't consider that initially. Back to the drawing board.

        Edit: What do you think the best way of representing the degree:min:sec is? I am leaning to simply converting everything to seconds, doing the arithmetic, and then converting to deg:min:sec format as Anomalous Monk did. I planned on extending the calculator to accept decimals anyway. But if I wanted to accept integer input, what would be the best way of representing this situation of small negatives?

        Storing the -0 as text does not appeal to me.

      This is no different from any decimal ...

      But if I have the decimal number -345, this is
          -(3*10^2 + 4*10^1 + 5*10^0)
      or
          -1 * (3*10^2 + 4*10^1 + 5*10^0)
      or
          -3*10^2 + -4*10^1 + -5*10^0
      or
          -3*10^2 - 4*10^1 - 5*10^0
      and not
          -3*10^2 + 4*10^1 + 5*10^0
      and similarly for numbers represented in sexagesimal base.

      Negative numbers are only permitted in the degree column.

      Unfortunately, if one has a d/m/s tuple  @dms = (3, 4, 5) one cannot negate it by writing -@dms. One has to negate each element:
          @neg_dms = map -1*$_, @dms;
      or (-3, -4, -5). IIUC, the notation -3° 4' 5" is equivalent to the tuple (-3°, -4', -5") analogously to decimal notation. Klaf is describing and giving an example of base-60 subtraction with borrowing, but that is not fundamentally different from base-10 subtraction.

      Update 1: Added the "Negative numbers ..." quote before the second paragraph for clarification, and various other minor wording changes and additions.

      Update 2: Here's the Klaf subtraction example in terms of normalizing everything to decimal arc-seconds, doing a decimal subtraction and reducing arc-seconds to a d/m/s tuple:

      c:\@Work\Perl\monks\thechartist>perl -wMstrict -le "sub dms_2_secs { my ($degs, $mins, $secs) = @_; ;; return $degs * 3600 + $mins * 60 + $secs; } ;; sub secs_2_dms { use integer; ;; my ($secs) = @_; ;; my $degs = $secs / 3600; $secs %= 3600; my $mins = $secs / 60; $secs %= 60; ;; return $degs, $mins, $secs; } ;; my $klaf_arc_secs = dms_2_secs(83, 18, 21) - dms_2_secs(39, 41, 28); my @klaf_dms = secs_2_dms($klaf_arc_secs); print qq{(@klaf_dms)}; " (43 36 53)
      (Update: The Klaf addition example also works correctly.) (Update: Moreover, the reversed subtraction  dms_2_secs(39, 41, 28) - dms_2_secs(83, 18, 21) yields the expected (-43 -36 -53) tuple.)


      Give a man a fish:  <%-{-{-{-<

        I agree that this alternate method is correct; my question now is if my transliteration of his base 60 algorithm has flaws that I did not initially see. I want to make an argument that these are 2 separate ways of describing the same point, but I do not have a proof yet.

        So far, the reduce sub is consistent with all of the examples in his text. User input would accept negative in the minute and second fields (unlike some other calculators), it just won't provide output with negatives in those fields, which are appropriately carried to the next highest term, as is done in this calculator http://www.mathopenref.com/dmscalculator.html

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1226341]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others exploiting the Monastery: (1)
As of 2024-04-25 00:16 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found