Skip to content

Instantly share code, notes, and snippets.

@renatoathaydes
Last active May 4, 2020 18:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save renatoathaydes/e015019c4283d6a54903a49d2887f59f to your computer and use it in GitHub Desktop.
Save renatoathaydes/e015019c4283d6a54903a49d2887f59f to your computer and use it in GitHub Desktop.
Calculating a number from its constituent parts (encoded as ASCII bytes)
import java.nio.charset.StandardCharsets;
class JavaComparison
{
public static void main(String[] args)
{
System.out.println("CUSTOM");
for (int i = 0; i < 100; i++)
{
custom();
}
System.out.println("JAVA");
for (int i = 0; i < 100; i++)
{
java();
}
System.out.println("CUSTOM");
for (int i = 0; i < 10; i++)
{
custom();
}
System.out.println("JAVA");
for (int i = 0; i < 10; i++)
{
java();
}
}
public static void java()
{
var s = "34.890625e10";
var b = s.getBytes(StandardCharsets.US_ASCII);
var r = System.nanoTime();
var result = Float.parseFloat(new String(b, StandardCharsets.US_ASCII));
var t = System.nanoTime() - r;
System.out.println("RESULT: " + result + "(took " + t + "ns)");
}
public static void custom()
{
byte[] bytes = bytes("34");
byte[] bytes1 = bytes("890625");
byte[] bytes2 = bytes("10");
var s = System.nanoTime();
var n = parseInt(bytes);
var f = parseFraction(bytes1);
var e = parseInt(bytes2);
var m = Math.pow(10, e);
var result = n * m + f * m;
var t = System.nanoTime() - s;
System.out.println("RESULT: " + result + "(took " + t + "ns)");
}
private static byte[] bytes(String s)
{
var b = s.getBytes(StandardCharsets.US_ASCII);
for (int i = 0; i < b.length; i++)
{
b[i] = (byte) (b[i] - 48);
}
return b;
}
private static int parseInt(byte[] bs)
{
int current = 0;
for (int i = 0; i < bs.length; i++)
{
var mult = (int) Math.pow(10, bs.length - i - 1);
var n = (bs[i] * mult);
current += n;
}
return current;
}
private static float parseFraction(byte[] bs)
{
float current = 0f;
for (int i = 0; i < bs.length; i++)
{
var mult = (float) Math.pow(10, -i - 1);
var n = (bs[i] * mult);
current += n;
}
return current;
}
}
import java.nio.charset.StandardCharsets;
class Scratch
{
public static void main(String[] args)
{
var n = parseInt(bytes("34"));
var f = parseFraction(bytes("890625"));
var e = parseInt(bytes("10"));
var m = Math.pow(10, e);
var result = n * m + f * m;
System.out.println("RESULT: " + result);
}
private static byte[] bytes(String s)
{
var b = s.getBytes(StandardCharsets.US_ASCII);
for (int i = 0; i < b.length; i++)
{
b[i] = (byte) (b[i] - 48);
}
return b;
}
private static int parseInt(byte[] bs)
{
int current = 0;
for (int i = 0; i < bs.length; i++)
{
var mult = (int) Math.pow(10, bs.length - i - 1);
var n = (bs[i] * mult);
System.out.println(n);
current += n;
}
return current;
}
private static float parseFraction(byte[] bs)
{
float current = 0f;
for (int i = 0; i < bs.length; i++)
{
var mult = (float) Math.pow(10, -i - 1);
var n = (bs[i] * mult);
System.out.println(n);
current += n;
}
return current;
}
}
@renatoathaydes
Copy link
Author

renatoathaydes commented May 4, 2020

The above shows an approximation algorithm for parsing floating-point numbers once its component parts are known, as parsed from a stream of US_ASCII bytes (or UTF-8 if already validated, as the bytes would be the same).

That's what the above code simulates.

In my machine, the last twenty runs (after 100 runs for each algorithm to warm up the JVM) show that the custom algorithm is around 10x times faster than using the lazy approach with the Java built-in parser (which, to be fair, uses a more accurate algorithm, but which is unlikely to matter in practice).

CUSTOM
RESULT: 3.4890625E11(took 2679ns)
RESULT: 3.4890625E11(took 2287ns)
RESULT: 3.4890625E11(took 2024ns)
RESULT: 3.4890625E11(took 1911ns)
RESULT: 3.4890625E11(took 2512ns)
RESULT: 3.4890625E11(took 2083ns)
RESULT: 3.4890625E11(took 2105ns)
RESULT: 3.4890625E11(took 2461ns)
RESULT: 3.4890625E11(took 2548ns)
RESULT: 3.4890625E11(took 2556ns)
JAVA
RESULT: 3.48906258E11(took 22857ns)
RESULT: 3.48906258E11(took 20474ns)
RESULT: 3.48906258E11(took 19918ns)
RESULT: 3.48906258E11(took 19208ns)
RESULT: 3.48906258E11(took 34852ns)
RESULT: 3.48906258E11(took 20863ns)
RESULT: 3.48906258E11(took 17852ns)
RESULT: 3.48906258E11(took 17362ns)
RESULT: 3.48906258E11(took 16861ns)
RESULT: 3.48906258E11(took 16314ns)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment