Skip to content

Instantly share code, notes, and snippets.

@nakhli
Last active September 26, 2015 03:38
Show Gist options
  • Save nakhli/1033234 to your computer and use it in GitHub Desktop.
Save nakhli/1033234 to your computer and use it in GitHub Desktop.
Numeric base convertion in C#, Java and Scala
// <copyright file="BaseX.cs" company="http://www.sinbadsoft.com">
// Copyright (c) Chaker Nakhli 2011
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
// License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
// applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
// </copyright>
// <author>Chaker Nakhli</author>
// <email>[email protected]</email>
// <date>2011/06/04</date>
namespace Javageneration
{
using System;
public static class BaseX
{
public static int Decode(string str, int baze)
{
int result = 0;
int place = 1;
int length = str.Length;
for (int i = 0; i < length; ++i)
{
result += Value(str[length - 1 - i]) * place;
place *= baze;
}
return result;
}
public static string Encode(int val, int baze)
{
var buffer = new char[32];
int place = 0;
int q = val;
do
{
buffer[place++] = Symbol(q % baze);
q /= baze;
}
while (q > 0);
Array.Reverse(buffer, 0, place);
return new string(buffer, 0, place);
}
public static unsafe string UnsafeEncode(int val, int baze)
{
char* buffer = stackalloc char[32];
int place = 0;
int q = val;
do
{
buffer[place++] = Symbol(q % baze);
q = q / baze;
}
while (q > 0);
for (int i = 0; i < place / 2; ++i)
{
int mirrorIndex = place - 1 - i;
char tmp = buffer[mirrorIndex];
buffer[mirrorIndex] = buffer[i];
buffer[i] = tmp;
}
return new string(buffer, 0, place);
}
public static int Value(char c)
{
if (c == '+') return 62;
if (c == '/') return 63;
if (c < '0') throw new ArgumentOutOfRangeException("c");
if (c < ':') return c - '0';
if (c < 'A') throw new ArgumentOutOfRangeException("c");
if (c < '[') return c - 'A' + 10;
if (c < 'a') throw new ArgumentOutOfRangeException("c");
if (c < '{') return c - 'a' + 36;
throw new ArgumentOutOfRangeException("c");
}
public static char Symbol(int i)
{
if (i < 0) throw new ArgumentOutOfRangeException("i");
if (i < 10) return (char)('0' + i);
if (i < 36) return (char)('A' + i - 10);
if (i < 62) return (char)('a' + i - 36);
if (i == 62) return '+';
if (i == 63) return '/';
throw new ArgumentOutOfRangeException("i");
}
}
}
// <copyright file="BaseX.java" company="http://www.sinbadsoft.com">
// Copyright (c) Chaker Nakhli 2011
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
// License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
// applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
// </copyright>
// <author>Chaker Nakhli</author>
// <email>[email protected]</email>
// <date>2011/06/04</date>
package com.javageneration;
public final class BaseX {
public static int decode(String str, int baze) {
int result = 0;
int place = 1;
int length = str.length();
for (int i = 0; i < length; ++i) {
result += Value(str.charAt(length - 1 - i)) * place;
place *= baze;
}
return result;
}
public static String encode(int val, int baze) {
char[] buffer = new char[32];
int place = 0;
int q = val;
do {
buffer[place++] = Symbol(q % baze);
q /= baze;
} while (q > 0);
for (int i = 0; i < place / 2; ++i) {
int mirrorIndex = place - 1 - i;
char tmp = buffer[mirrorIndex];
buffer[mirrorIndex] = buffer[i];
buffer[i] = tmp;
}
return new String(buffer, 0, place);
}
public static int Value(char c) {
if (c == '+') return 62;
if (c == '/') return 63;
if (c < '0') throw new IndexOutOfBoundsException("c");
if (c < ':') return c - '0';
if (c < 'A') throw new IndexOutOfBoundsException("c");
if (c < '[') return c - 'A' + 10;
if (c < 'a') throw new IndexOutOfBoundsException("c");
if (c < '{') return c - 'a' + 36;
throw new IndexOutOfBoundsException("c");
}
public static char Symbol(int i) {
if (i < 0) throw new IndexOutOfBoundsException("i");
if (i < 10) return (char) ('0' + i);
if (i < 36) return (char) ('A' + i - 10);
if (i < 62) return (char) ('a' + i - 36);
if (i == 62) return '+';
if (i == 63) return '/';
throw new IndexOutOfBoundsException("i");
}
}
// <copyright file="BaseX.scala" company="http://www.sinbadsoft.com">
// Copyright (c) Chaker Nakhli 2011
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
// License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by
// applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
// governing permissions and limitations under the License.
// </copyright>
// <author>Chaker Nakhli</author>
// <email>[email protected]</email>
// <date>2011/06/04</date>
package com.javageneration
object BaseX extends ValueAndSymbolProvider {
def encode(value: Int, baze: Int): String = {
def process(q: Int, place: Int, baze: Int, builder: StringBuilder): StringBuilder = {
if (q > 0) process(q / baze, place + 1, baze, builder += symbol(q % baze))
else builder
}
if (value == 0) symbol(0).toString
else process(value, 0, baze, new StringBuilder(32)).reverse.toString
}
def decode(str: String, baze: Int): Int = {
def process(acc: Int, place: Int, str: String, index: Int): Int = {
if (index >= 0) process(acc + value(str.charAt(index)) * place, place * baze, str, index-1)
else acc
}
process(0, 1, str, str.length - 1)
}
}
object BaseXListBased extends ValueAndSymbolProvider {
def encode(i: Int, baze: Int): String = {
def process(q: Int, baze: Int, list: List[Char]): List[Char] = {
if (q > 0) process(q / baze, baze, symbol(q % baze) :: list)
else list
}
if (i == 0) symbol(0).toString
else process(i, baze, Nil).mkString
}
def decode(str: String, baze: Int): Int = {
def process(acc: Int, place: Int, lst: List[Char]): Int = {
if (!lst.isEmpty) process(acc + value(lst.head) * place, place * baze, lst.tail)
else acc
}
process(0, 1, str.reverse.toList)
}
}
trait ValueAndSymbolProvider {
def value(c: Char): Int = {
if (c == '+') 62
else if (c == '/') 63
else if (c < '0') throw new IndexOutOfBoundsException("c");
else if (c < ':') c - '0';
else if (c < 'A') throw new IndexOutOfBoundsException("c");
else if (c < '[') c - 'A' + 10;
else if (c < 'a') throw new IndexOutOfBoundsException("c");
else if (c < '{') c - 'a' + 36;
else throw new IndexOutOfBoundsException("c");
}
def symbol(i: Int): Char = {
if (i < 0) throw new IndexOutOfBoundsException("i")
else if (i < 10) ('0' + i).toChar
else if (i < 36) ('A' + i - 10).toChar
else if (i < 62) ('a' + i - 36).toChar
else if (i == 62) '+'
else if (i == 63) '/'
else throw new IndexOutOfBoundsException("i");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment