Negative base numbers: Difference between revisions

From Rosetta Code
Content added Content deleted
m (→‎{{header|Perl 6}}: fix spacing)
(→‎{{header|Perl 6}}: Use subroutines rather than methods to avoid monkey patching. Expand to accept up to base -36.)
Line 10: Line 10:
=={{header|Perl 6}}==
=={{header|Perl 6}}==
{{works with|Rakudo|2016.11}}
{{works with|Rakudo|2016.11}}
Perl 6 provides built-in methods base and parse-base to convert to and from bases 2 through 36. We'll just augment the core methods to accept negative bases. We'll simplify things by only dealing with negative bases from -2 through -10.
Perl 6 provides built-in methods / routines base and parse-base to convert to and from bases 2 through 36. We'll just shadow the core routines with versions that accept negative bases. We'll simplify things by only accepting integer values to convert.


<lang perl6>use MONKEY-TYPING; # We're messing around with core types
<lang perl6>multi sub base (Int $value, Int $radix where -37 < * < -1) {
my @result = $value.polymod($radix xx *);

for @result.kv -> $k, $v {
augment class Int {
multi method base (Int $radix where -11 < * < -1) {
if $v < 0 {
my @result = self.polymod($radix xx *);
@result[$k ] -= $radix;
for @result.kv -> $k, $v {
@result[$k + 1] += 1;
if $v < 0 {
@result[$k ] -= $radix;
@result[$k + 1] += 1;
}
}
}
+ flip [~] @result;
}
}
@result.pop while @result.tail == 0;
@result».=base($radix.abs);
flip [~] @result;
}


multi method parse-base (Int $radix where -11 < * < -1) {
multi sub parse-base (Str $str, Int $radix where -37 < * < -1) {
[+] self.flip.comb.kv.map: { $^v * $radix ** $^k }
[+] $str.flip.comb.kv.map: { $^v.parse-base($radix.abs) * $radix ** $^k }
}
}
}


# TESTING
# TESTING
say ' 10.base( -2) = ', 10.base(-2);
say ' 10.&base( -2) = ', 10.&base(-2);
say '146.base( -3) = ', 146.base(-3);
say '146.&base( -3) = ', 146.&base(-3);
say ' 15.base(-10) = ', 15.base(-10);
say ' 15.&base(-10) = ', 15.&base(-10);
say '107.&base(-16) = ', 107.&base(-16);


say '11110.parse-base( -2) = ', 11110.parse-base(-2);
say '"11110".&parse-base( -2) = ', "11110".&parse-base(-2);
say '21102.parse-base( -3) = ', 21102.parse-base(-3);
say '"21102".&parse-base( -3) = ', "21102".&parse-base(-3);
say ' 195.parse-base(-10) = ', 195.parse-base(-10);</lang>
say ' "195".&parse-base(-10) = ', "195".&parse-base(-10);
say ' "1AB".&parse-base(-16) = ', "1AB".&parse-base(-16);</lang>
{{out}}
{{out}}
<pre> 10.base( -2) = 11110
<pre> 10.&base( -2) = 11110
146.base( -3) = 21102
146.&base( -3) = 21102
15.base(-10) = 195
15.&base(-10) = 195
11110.parse-base( -2) = 10
107.&base(-16) = 1AB
21102.parse-base( -3) = 146
"11110".&parse-base( -2) = 10
195.parse-base(-10) = 15</pre>
"21102".&parse-base( -3) = 146
"195".&parse-base(-10) = 15
"1AB".&parse-base(-16) = 107</pre>


=={{header|Python}}==
=={{header|Python}}==

Revision as of 13:02, 16 December 2016

Negative base numbers is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Negative base numbers are an alternatively way to encode numbers without the need for a minus sign. Various negative bases may be used including negadecimal (base -10), negabinary (-2) and negaternary (-3).[1][2]

Task
  • Encode the decimal number 10 as negabinary
  • Encode the decimal number 146 as negaternary (expect 21102)
  • Encode the decimal number 15 as negadecimal (expect 195)
  • In each of the above cases, convert the encoded number back to decimal.

Perl 6

Works with: Rakudo version 2016.11

Perl 6 provides built-in methods / routines base and parse-base to convert to and from bases 2 through 36. We'll just shadow the core routines with versions that accept negative bases. We'll simplify things by only accepting integer values to convert.

<lang perl6>multi sub base (Int $value, Int $radix where -37 < * < -1) {

   my @result = $value.polymod($radix xx *);
   for @result.kv -> $k, $v {
       if $v < 0 {
           @result[$k    ] -= $radix;
           @result[$k + 1] += 1;
       }
   }
   @result.pop while @result.tail == 0;
   @result».=base($radix.abs);
   flip [~] @result;

}

multi sub parse-base (Str $str, Int $radix where -37 < * < -1) {

   [+] $str.flip.comb.kv.map: { $^v.parse-base($radix.abs) * $radix ** $^k }

}

  1. TESTING

say ' 10.&base( -2) = ', 10.&base(-2); say '146.&base( -3) = ', 146.&base(-3); say ' 15.&base(-10) = ', 15.&base(-10); say '107.&base(-16) = ', 107.&base(-16);

say '"11110".&parse-base( -2) = ', "11110".&parse-base(-2); say '"21102".&parse-base( -3) = ', "21102".&parse-base(-3); say ' "195".&parse-base(-10) = ', "195".&parse-base(-10); say ' "1AB".&parse-base(-16) = ', "1AB".&parse-base(-16);</lang>

Output:
 10.&base( -2) = 11110
146.&base( -3) = 21102
 15.&base(-10) = 195
107.&base(-16) = 1AB
"11110".&parse-base( -2) = 10
"21102".&parse-base( -3) = 146
  "195".&parse-base(-10) = 15
  "1AB".&parse-base(-16) = 107

Python

<lang python>#!/bin/python from __future__ import print_function

def EncodeNegBase(n, b): #Converts from decimal if n == 0: return "0" out = [] while n != 0: n, rem = divmod(n, b) if rem < 0: n += 1 rem -= b out.append(rem) return "".join(map(str, out[::-1]))

def DecodeNegBase(nstr, b): #Converts to decimal if nstr == "0": return 0

total = 0 for i, ch in enumerate(nstr[::-1]): total += int(ch) * b**i return total

if __name__=="__main__":

print ("Encode 10 as negabinary (expect 11110)") result = EncodeNegBase(10, -2) print (result) if DecodeNegBase(result, -2) == 10: print ("Converted back to decimal") else: print ("Error converting back to decimal")

print ("Encode 146 as negaternary (expect 21102)") result = EncodeNegBase(146, -3) print (result) if DecodeNegBase(result, -3) == 146: print ("Converted back to decimal") else: print ("Error converting back to decimal")

print ("Encode 15 as negadecimal (expect 195)") result = EncodeNegBase(15, -10) print (result) if DecodeNegBase(result, -10) == 15: print ("Converted back to decimal") else: print ("Error converting back to decimal")</lang>

Output:
Encode 10 as negabinary (expect 11110)
11110
Converted back to decimal
Encode 146 as negaternary (expect 21102)
21102
Converted back to decimal
Encode 15 as negadecimal (expect 195)
195
Converted back to decimal

References