js-hexfloat
v0.4.6
Published
Rudimentary C99 Hexadecimal Floating Point Support in JS
Downloads
5
Readme
js-hexfloat
Rudimentary C99 Hexadecimal Floating Point Support in JS
SYNOPSIS
var pi = parseHexFloat('0x1.921fb54442d18p+1'); // 3.14159265358982
var piHex = Math.PI.toHexString(); // '0x1.921fb54442d18p+1'
parseHexFloat(piHex) == Math.PI; // true
DESCRIPTION
This script adds the following:
parseHexFloat(theString)
Parses C99 hexadecimal floating point in theString
. Returns NaN
if fails.
Unlike parseInt
and parseFloat
, the number must be prepended with '0x' and ended with 'p' and exponent in decimal number.
also available as Number.parseHexFloat()
.
parseHexFloat
as a callback
From version 0.4.0, you can use parseHexFloat
with String.prototype.replace
.
var text = 'e=0x1.5bf0a8b145769p+1, pi=0x1.921fb54442d18p+1';
text.replace(RE_HEXFLOAT_G, parseHexFloat) // 'e=2.718281828459045, pi=3.141592653589793';
In the case above, parseHexFloat does not apply regexp by itself. Instead it just takes its arguments
as the matched result.
Unfortunately text.replace(RE_HEXFLOAT, parseHexFloat, 'g')
is not standard so RE_HEXFLOAT_G
is added.
RE_HEXFLOAT
RegExp
object used in parseHexFloat
:
/([\+\-]?)0x([0-9A-F]+)\.?([0-9A-F]*)p([\+\-]?[0-9]+)/i
RE_HEXFLOAT_G
RE_HEXFLOAT
with a g
(global) flag. See above for usage.
Number.prototype.toHexString()
Stringifies the number as a C99 hexadecimal notation like "%a"
in C99 sprintf()
.
Why Canonical Form?
From version 0.3.0, .toHexString()
always returns the canonical notation.
Math.PI.toString(16); // 3.243f6a8885a3 -> 0x3.243f6a8885a3p0 is valid yet uncanonical
Math.PI.toHexString(); // 0x1.921fb54442d18p+1 is valid and canonical
It seems ok to just prepend '0x' and append 'p0' to .toString(16)
to make a hex float. Turns out it isn't. It sometimes drops the last bits in some occasions.
Math.log(2).toString(16) // 0.b17217f7d1cf78
Math.log(2).toHexString() // 0x1.62e42fefa39efp-1
% perl -E 'say 0x0.b17217f7d1cf78p0 - 0x1.62e42fefa39efp-1'
-1.11022302462516e-16
% perl -E 'say sprintf "%a", 0x0.b17217f7d1cf78p0 - 0x1.62e42fefa39efp-1'
-0x1p-53
And abs(-0x1p-53)
is DBL_EPSILON
.
SEE ALSO
- http://www.exploringbinary.com/hexadecimal-floating-point-constants/
Appendix: HexFloat in Other Languages
- C
- Standard since C99
- Literals, output via
%a
inprintf
format, input viastrtod()
, ... - https://gcc.gnu.org/onlinedocs/gcc/Hex-Floats.html
- C++
- Standard since C++11
- C features plus
std::hexfloat
, ... - http://www.cplusplus.com/reference/ios/hexfloat/
- Perl 5
- Supported since 5.22
- Pretty much like C99: literals, the
%a
format,POSIX::strtod()
, ... - http://perldoc.perl.org/perl5220delta.html
- http://www.effectiveperlprogramming.com/2015/06/perl-v5-22-adds-hexadecimal-floating-point-literals/
- Ruby
- Supported since 1.9?
- http://docs.ruby-lang.org/ja/1.9.3/doc/print_format.html
- http://docs.ruby-lang.org/ja/1.8.7/doc/print_format.html
- No literals, output via
%a
forsprintf
, input viaFloat()
- Supported since 1.9?
- Swift
- Supported from the beginning
- Literals, output via
String(format:"%a", ...)
, input viaDouble()
, ... - https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/