Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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

This comment has been minimized.

Copy link
Owner Author

@renatoathaydes 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