budman has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I have an array in which the first element is either -0 or +0 (returned from the DateCalc function). How can I apply the flag value to all the values in the rest of the array.

I tried from the command line, but found a wierd quirk with -0. In order for it to work correctly, it looks like I need to use it as a string array.

perl -le '@B=qw(-0 4);$g=($B[0] lt 0?-1:1); printf"%s\n" x 3,$B[0],$g,$B[1]*$g' -0 -1 -4 perl -le '@B=(-0,4);$g=($B[0] < 0?-1:1); printf"%s\n" x 3,$B[0],$g,$B[1]*$g' 0 1 4
Can the map or regex substitute command take the sign value and apply it to the remainder of the array?

Thanks budman

Replies are listed 'Best First'.
Re: Applying Sign Bit
by mattr (Curate) on Jan 22, 2004 at 09:17 UTC
    I feel for you but there really should exist nothing like a number called -0 or +0. It looks ambiguous as to whether qw will think it is true or not. It is really an imaginary conundrum and dependent on unwritten rules of logic and how perl interprets it. Why not replace the second character of $B[0] with a 1 so you have +1 or -1? That way you can stay sane. :>
    $ perl -le '@B=qw(-0 4 5 6); $B[0] = substr($B[0],0,1) . 1; print map $B[0]*$_ . " ", @B[1..3];' -4 -5 -6
Re: Applying Sign Bit
by Abigail-II (Bishop) on Jan 22, 2004 at 09:42 UTC
    How can I apply the flag value to all the values in the rest of the array.
    What is a "flag value" and how can you apply it on something?
    In order for it to work correctly, it looks like I need to use it as a string array.
    Perl doesn't know "string" arrays. Perl has scalars, and will make it act as a number if you use it as a number, and will make it act as a string if you use it as a string.

    -0 as a string consists of two characters, the first a minus symbol, the second a zero. -0 as a number is the same as 0.

    Abigail

Re: Applying Sign Bit
by Anonymous Monk on Jan 22, 2004 at 14:12 UTC
    Since perl doesn't implement copysign or signbit and won't let you divide by zero, the best bet is to just check for the minus:
    $sign = $B[0] =~ /^\s*-/ ? -1 : 1; @result = map {$_*$sign} @B[1..$#B];
Re: Applying Sign Bit
by hardburn (Abbot) on Jan 22, 2004 at 14:43 UTC

    Mathmatically, zero is neither positive or negative. What you see is the result of Perl fudging a little.

    Also, there is no "flag" value for negative numbers, at least not in the way you're probably thinking. See Twos-complement on Wikipedia. Although the concept is more complex than a simple flag value, it ends up simplifying the logic required for using signed numbers.

    ----
    I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
    -- Schemer

    : () { :|:& };:

    Note: All code is untested, unless otherwise stated

      Also, there is no "flag" value for negative numbers
      Actually, there is. In perl, numbers are normally floating point. Most machines nowadays use IEEE standard floats, which are sign-magnitude, not two's complement. Being able to calculate 1/(-0)=-Inf is supposed to make things easier for certain numerical algorithms.

        While I know a bit about this but I personally would be appreciative if you or someone else well versed in this subject did a meditation on it. Especially from the Perl perspective. (Like Abigails trick of a real small negative number turning into -0.)

        I dont normally upvote anonymonk posts, but I did yours. Thanks.


        ---
        demerphq

          First they ignore you, then they laugh at you, then they fight you, then you win.
          -- Gandhi


Re: Applying Sign Bit
by jdtoronto (Prior) on Jan 22, 2004 at 14:58 UTC
    Well, it's wierd that Date::Calc is doing that - returning a value of -0 that is. Because you cannot test for +0 or -0, think about it, 0 is zero. Add 1 to it and +0 becomes one, but so does minus 0. In fact the returned value has no significance or value, so you bneed to ask "why is Date::Calc returning a nonense value?". It may in fact mean that you are calling it invalidly and it is trying to DWIM with your request.

    Maybe a code fragment that illustrates the situation would be helpful.

    jdtoronto

      so you bneed to ask "why is Date::Calc returning a nonense value?"
      No. The question to ask is What is Date::Calc returning?. What you do know is that it appears as -0 when printed. It could be a string. It could be an overloaded object. But since Date::Calc deals with numbers, it's probably a number. Now, we all know that floats can't always be represented exactly. So, could it be that -0 represents a small negative value, small enough that it stringifies to -0? Let's try:
      $ perl -wle 'print -1 / (10 ** 5000)' -0 $
      I guess it can.

      Note that the code of the OP was using -0 literals, which are a totally different kind of beast.

      Abigail

      When comparing 2 dates the DateCalc(d1,d2) function will return +0:0:WW:HH:MM:SS if the d2 > d1, and -0:0:WW:HH:MM:SS if d1 > d2. I think that is return type 0, and there is another return type that shows Years, Months, Days.

      If that return value was +1 or -1 then you can just multiple each item with the "flag" to apply the sign bit. I call it a flag, because it only has 2 states -0 or +0.

      Thanks for all the suggestions. I thought I might have overlooked a command that would do this. In the program, I opted to use another method of testings that proved to be more efficient. However, this applying a sign bit bugged me. I just needed to know. :) For future reference and to ease my mind.

      Here is another, shouldn't 1 + -0 = -1 ?

      budman
        shouldn't 1 + -0 = -1 ?
        No. If you subtracted 1 from each side, you'd have 0 + -0 = -2. That would be bizarre.