aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--erts/doc/src/erlang.xml53
-rw-r--r--erts/emulator/beam/bif.c187
-rw-r--r--erts/emulator/beam/bif.tab3
-rw-r--r--erts/emulator/test/num_bif_SUITE.erl193
-rw-r--r--erts/preloaded/src/erlang.erl31
-rw-r--r--lib/compiler/src/erl_bifs.erl2
-rw-r--r--lib/stdlib/src/erl_internal.erl3
-rw-r--r--lib/tools/emacs/erlang.el2
-rw-r--r--system/doc/reference_manual/data_types.xml6
9 files changed, 325 insertions, 155 deletions
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml
index 36d606130f..06fefa8efb 100644
--- a/erts/doc/src/erlang.xml
+++ b/erts/doc/src/erlang.xml
@@ -300,6 +300,18 @@
</desc>
</func>
<func>
+ <name name="binary_to_float" arity="1"/>
+ <fsummary>Convert from text representation to a float</fsummary>
+ <desc>
+ <p>Returns the float whose text representation is <c><anno>Binary</anno></c>.</p>
+ <pre>
+> <input>binary_to_float(&lt;&lt;"2.2017764e+0">>).</input>
+2.2017764</pre>
+ <p>Failure: <c>badarg</c> if <c><anno>Binary</anno></c> contains a bad
+ representation of a float.</p>
+ </desc>
+ </func>
+ <func>
<name name="binary_to_integer" arity="1"/>
<fsummary>Convert from text representation to an integer</fsummary>
<desc>
@@ -987,26 +999,38 @@ true
</desc>
</func>
<func>
- <name name="float_to_list" arity="1"/>
+ <name name="float_to_binary" arity="1"/>
<fsummary>Text representation of a float</fsummary>
<desc>
- <p>Returns a string which corresponds to the text
- representation of <c><anno>Float</anno></c>.</p>
+ <p>The same as <c>float_to_binary(<anno>Float</anno>,[{scientific,20}])</c>.</p>
+ </desc>
+ </func>
+ <func>
+ <name name="float_to_binary" arity="2"/>
+ <fsummary>Text representation of a float formatted using given options</fsummary>
+ <desc>
+ <p>Returns a binary which corresponds to the text
+ representation of <c><anno>Float</anno></c> using fixed decimal
+ point formatting. The <c><anno>Options</anno></c> behave in the same
+ way as <seealso marker="#float_to_list/2">float_to_list/2</seealso>.
+ </p>
<pre>
-> <input>float_to_list(7.0).</input>
-"7.00000000000000000000e+00"</pre>
+> <input>float_to_binary(7.12, [{decimals, 4}]).</input>
+&lt;&lt;"7.1200">>
+> <input>float_to_binary(7.12, [{decimals, 4}, compact]).</input>
+&lt;&lt;"7.12">></pre>
+ </desc>
+ </func>
+ <func>
+ <name name="float_to_list" arity="1"/>
+ <fsummary>Text representation of a float</fsummary>
+ <desc>
+ <p>The same as <c>float_to_list(<anno>Float</anno>,[{scientific,20}])</c>.</p>
</desc>
</func>
<func>
- <name>float_to_list(Float, Options) -> string()</name>
+ <name name="float_to_list" arity="2"/>
<fsummary>Text representation of a float formatted using given options</fsummary>
- <type>
- <v>Float = float()</v>
- <v>Options = [Option]</v>
- <v>Option = {decimals, Decimals::0..253} |
- {scientific, Decimals::0..249} |
- compact</v>
- </type>
<desc>
<p>Returns a string which corresponds to the text
representation of <c>Float</c> using fixed decimal point formatting.
@@ -1019,7 +1043,8 @@ true
only meaningful together with the <c>decimals</c> option). When
<c>scientific</c> option is provided, the float will be formatted using
scientific notation with <c>Decimals</c> digits of precision. If
- <c>Options</c> is <c>[]</c> the function behaves like <c>float_to_list/1</c>.
+ <c>Options</c> is <c>[]</c> the function behaves like
+ <c><seealso marker="#float_to_list/1">float_to_list/1</seealso></c>.
</p>
<pre>
> <input>float_to_list(7.12, [{decimals, 4}]).</input>
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index a596068527..5adcf6d5c7 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -39,6 +39,7 @@
#include "erl_thr_progress.h"
#define ERTS_PTAB_WANT_BIF_IMPL__
#include "erl_ptab.h"
+#include "erl_bits.h"
static Export* flush_monitor_message_trap = NULL;
static Export* set_cpu_topology_trap = NULL;
@@ -2955,29 +2956,9 @@ BIF_RETTYPE list_to_integer_2(BIF_ALIST_2)
/**********************************************************************/
-/* convert a float to a list of ascii characters */
+static int do_float_to_charbuf(Process *p, Eterm efloat, Eterm list,
+ char *fbuf, int sizeof_fbuf) {
-BIF_RETTYPE float_to_list_1(BIF_ALIST_1)
-{
- int i;
- Uint need;
- Eterm* hp;
- FloatDef f;
- char fbuf[30];
-
- /* check the arguments */
- if (is_not_float(BIF_ARG_1))
- BIF_ERROR(BIF_P, BADARG);
- GET_DOUBLE(BIF_ARG_1, f);
- if ((i = sys_double_to_chars(f.fd, fbuf, sizeof(fbuf))) <= 0)
- BIF_ERROR(BIF_P, EXC_INTERNAL_ERROR);
- need = i*2;
- hp = HAlloc(BIF_P, need);
- BIF_RET(buf_to_intlist(&hp, fbuf, i, NIL));
-}
-
-BIF_RETTYPE float_to_list_2(BIF_ALIST_2)
-{
const static int arity_two = make_arityval(2);
int decimals = SYS_DEFAULT_FLOAT_DECIMALS;
int compact = 0;
@@ -2986,16 +2967,11 @@ BIF_RETTYPE float_to_list_2(BIF_ALIST_2)
FMT_FIXED,
FMT_SCIENTIFIC
} fmt_type = FMT_LEGACY;
- Eterm list = BIF_ARG_2;
Eterm arg;
- int i;
- Uint need;
- Eterm* hp;
FloatDef f;
- char fbuf[256];
/* check the arguments */
- if (is_not_float(BIF_ARG_1))
+ if (is_not_float(efloat))
goto badarg;
for(; is_list(list); list = CDR(list_val(list))) {
@@ -3023,22 +2999,64 @@ BIF_RETTYPE float_to_list_2(BIF_ALIST_2)
goto badarg;
}
- GET_DOUBLE(BIF_ARG_1, f);
+ GET_DOUBLE(efloat, f);
if (fmt_type == FMT_FIXED) {
- if ((i = sys_double_to_chars_fast(f.fd, fbuf, sizeof(fbuf),
- decimals, compact)) <= 0)
- goto badarg;
+ return sys_double_to_chars_fast(f.fd, fbuf, sizeof_fbuf,
+ decimals, compact);
} else {
- if ((i = sys_double_to_chars_ext(f.fd, fbuf, sizeof(fbuf), decimals)) <= 0)
- goto badarg;
+ return sys_double_to_chars_ext(f.fd, fbuf, sizeof_fbuf, decimals);
}
- need = i*2;
- hp = HAlloc(BIF_P, need);
- BIF_RET(buf_to_intlist(&hp, fbuf, i, NIL));
badarg:
+ return -1;
+}
+
+/* convert a float to a list of ascii characters */
+
+static BIF_RETTYPE do_float_to_list(Process *BIF_P, Eterm arg, Eterm opts) {
+ int used;
+ Eterm* hp;
+ char fbuf[256];
+
+ if ((used = do_float_to_charbuf(BIF_P,arg,opts,fbuf,sizeof(fbuf))) <= 0) {
BIF_ERROR(BIF_P, BADARG);
+ }
+ hp = HAlloc(BIF_P, (Uint)used*2);
+ BIF_RET(buf_to_intlist(&hp, fbuf, (Uint)used, NIL));
+}
+
+
+BIF_RETTYPE float_to_list_1(BIF_ALIST_1)
+{
+ return do_float_to_list(BIF_P,BIF_ARG_1,NIL);
+}
+
+BIF_RETTYPE float_to_list_2(BIF_ALIST_2)
+{
+ return do_float_to_list(BIF_P,BIF_ARG_1,BIF_ARG_2);
+}
+
+/* convert a float to a binary of ascii characters */
+
+static BIF_RETTYPE do_float_to_binary(Process *BIF_P, Eterm arg, Eterm opts) {
+ int used;
+ char fbuf[256];
+
+ if ((used = do_float_to_charbuf(BIF_P,arg,opts,fbuf,sizeof(fbuf))) <= 0) {
+ BIF_ERROR(BIF_P, BADARG);
+ }
+ BIF_RET(new_binary(BIF_P, (byte*)fbuf, (Uint)used));
+}
+
+BIF_RETTYPE float_to_binary_1(BIF_ALIST_1)
+{
+ return do_float_to_binary(BIF_P,BIF_ARG_1,NIL);
+}
+
+BIF_RETTYPE float_to_binary_2(BIF_ALIST_2)
+{
+ return do_float_to_binary(BIF_P,BIF_ARG_1,BIF_ARG_2);
}
/**********************************************************************/
@@ -3223,36 +3241,101 @@ BIF_RETTYPE string_to_float_1(BIF_ALIST_1)
BIF_RET(tup);
}
+static BIF_RETTYPE do_charbuf_to_float(Process *BIF_P,char *buf) {
+ FloatDef f;
+ Eterm res;
+ Eterm* hp;
+
+ if (sys_chars_to_double(buf, &f.fd) != 0)
+ BIF_ERROR(BIF_P, BADARG);
+
+ hp = HAlloc(BIF_P, FLOAT_SIZE_OBJECT);
+ res = make_float(hp);
+ PUT_DOUBLE(f, hp);
+ BIF_RET(res);
+
+}
BIF_RETTYPE list_to_float_1(BIF_ALIST_1)
{
int i;
- FloatDef f;
Eterm res;
- Eterm* hp;
char *buf = NULL;
i = list_length(BIF_ARG_1);
- if (i < 0) {
- badarg:
- if (buf)
- erts_free(ERTS_ALC_T_TMP, (void *) buf);
- BIF_ERROR(BIF_P, BADARG);
- }
-
+ if (i < 0)
+ BIF_ERROR(BIF_P, BADARG);
+
buf = (char *) erts_alloc(ERTS_ALC_T_TMP, i + 1);
if (intlist_to_buf(BIF_ARG_1, buf, i) < 0)
- goto badarg;
+ goto list_to_float_1_error;
buf[i] = '\0'; /* null terminal */
+
+ if ((res = do_charbuf_to_float(BIF_P,buf)) == THE_NON_VALUE)
+ goto list_to_float_1_error;
+
+ erts_free(ERTS_ALC_T_TMP, (void *) buf);
+ BIF_RET(res);
+
+ list_to_float_1_error:
+ erts_free(ERTS_ALC_T_TMP, (void *) buf);
+ BIF_ERROR(BIF_P, BADARG);
+
+}
+
+BIF_RETTYPE binary_to_float_1(BIF_ALIST_1)
+{
+ Eterm res;
+ Eterm binary = BIF_ARG_1;
+ Sint size;
+ byte* bytes, *buf;
+ Eterm* real_bin;
+ Uint offs = 0;
+ Uint bit_offs = 0;
+
+ if (is_not_binary(binary) || (size = binary_size(binary)) == 0)
+ BIF_ERROR(BIF_P, BADARG);
+
+ /*
+ * Unfortunately we have to copy the binary because we have to insert
+ * the '\0' at the end of the binary for strtod to work
+ * (there is no nstrtod :( )
+ */
+
+ buf = erts_alloc(ERTS_ALC_T_TMP, size + 1);
+
+ real_bin = binary_val(binary);
+ if (*real_bin == HEADER_SUB_BIN) {
+ ErlSubBin* sb = (ErlSubBin *) real_bin;
+ if (sb->bitsize) {
+ goto binary_to_float_1_error;
+ }
+ offs = sb->offs;
+ bit_offs = sb->bitoffs;
+ real_bin = binary_val(sb->orig);
+ }
+ if (*real_bin == HEADER_PROC_BIN) {
+ bytes = ((ProcBin *) real_bin)->bytes + offs;
+ } else {
+ bytes = (byte *)(&(((ErlHeapBin *) real_bin)->data)) + offs;
+ }
+ if (bit_offs)
+ erts_copy_bits(bytes, bit_offs, 1, buf, 0, 1, size*8);
+ else
+ memcpy(buf, bytes, size);
+
+ buf[size] = '\0';
+
+ if ((res = do_charbuf_to_float(BIF_P,(char*)buf)) == THE_NON_VALUE)
+ goto binary_to_float_1_error;
- if (sys_chars_to_double(buf, &f.fd) != 0)
- goto badarg;
- hp = HAlloc(BIF_P, FLOAT_SIZE_OBJECT);
- res = make_float(hp);
- PUT_DOUBLE(f, hp);
erts_free(ERTS_ALC_T_TMP, (void *) buf);
BIF_RET(res);
+
+ binary_to_float_1_error:
+ erts_free(ERTS_ALC_T_TMP, (void *) buf);
+ BIF_ERROR(BIF_P, BADARG);
}
/**********************************************************************/
diff --git a/erts/emulator/beam/bif.tab b/erts/emulator/beam/bif.tab
index aa6105de73..b74dc5c3fe 100644
--- a/erts/emulator/beam/bif.tab
+++ b/erts/emulator/beam/bif.tab
@@ -565,6 +565,9 @@ bif erlang:binary_to_integer/1
bif erlang:binary_to_integer/2
bif erlang:integer_to_binary/1
bif erlang:list_to_integer/2
+bif erlang:float_to_binary/1
+bif erlang:float_to_binary/2
+bif erlang:binary_to_float/1
#
# Obsolete
diff --git a/erts/emulator/test/num_bif_SUITE.erl b/erts/emulator/test/num_bif_SUITE.erl
index 92ef456fe8..b92a0e2059 100644
--- a/erts/emulator/test/num_bif_SUITE.erl
+++ b/erts/emulator/test/num_bif_SUITE.erl
@@ -37,22 +37,22 @@
-export([all/0, suite/0, groups/0, init_per_suite/1, end_per_suite/1,
init_per_group/2, end_per_group/2, t_abs/1, t_float/1,
- t_float_to_list/1, t_integer_to_string/1,
+ t_float_to_string/1, t_integer_to_string/1,
t_string_to_integer/1,
- t_list_to_float_safe/1, t_list_to_float_risky/1,
+ t_string_to_float_safe/1, t_string_to_float_risky/1,
t_round/1, t_trunc/1
]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
- [t_abs, t_float, t_float_to_list, t_integer_to_string,
- {group, t_list_to_float}, t_string_to_integer, t_round,
+ [t_abs, t_float, t_float_to_string, t_integer_to_string,
+ {group, t_string_to_float}, t_string_to_integer, t_round,
t_trunc].
groups() ->
- [{t_list_to_float, [],
- [t_list_to_float_safe, t_list_to_float_risky]}].
+ [{t_string_to_float, [],
+ [t_string_to_float_safe, t_string_to_float_risky]}].
init_per_suite(Config) ->
Config.
@@ -112,111 +112,136 @@ t_float(Config) when is_list(Config) ->
ok.
-%% Tests float_to_list/1, float_to_list/2.
-
-t_float_to_list(Config) when is_list(Config) ->
- test_ftl("0.0e+0", 0.0),
- test_ftl("2.5e+1", 25.0),
- test_ftl("2.5e+0", 2.5),
- test_ftl("2.5e-1", 0.25),
- test_ftl("-3.5e+17", -350.0e15),
- "1.00000000000000000000e+00" = float_to_list(1.0),
- "1.00000000000000000000e+00" = float_to_list(1.0, []),
- "-1.00000000000000000000e+00" = float_to_list(-1.0, []),
- "-1.00000000000000000000" = float_to_list(-1.0, [{decimals, 20}]),
- {'EXIT', {badarg, _}} = (catch float_to_list(1.0, [{decimals, -1}])),
- {'EXIT', {badarg, _}} = (catch float_to_list(1.0, [{decimals, 254}])),
- {'EXIT', {badarg, _}} = (catch float_to_list(1.0, [{scientific, 250}])),
- {'EXIT', {badarg, _}} = (catch float_to_list(1.0e+300, [{decimals, 1}])),
- "1.0e+300" = float_to_list(1.0e+300, [{scientific, 1}]),
- "1.0" = float_to_list(1.0, [{decimals, 249}, compact]),
- "1" = float_to_list(1.0, [{decimals, 0}]),
- "2" = float_to_list(1.9, [{decimals, 0}]),
- "123456789012345680.0" = erlang:float_to_list(
- 123456789012345678.0, [{decimals, 236}, compact]),
- {'EXIT', {badarg, _}} = (catch float_to_list(
- 123456789012345678.0, [{decimals, 237}])),
- Expected = "1." ++ string:copies("0", 249) ++ "e+00",
- Expected = float_to_list(1.0, [{scientific, 249}, compact]),
+%% Tests float_to_list/1, float_to_list/2, float_to_binary/1, float_to_binary/2
+
+t_float_to_string(Config) when is_list(Config) ->
+ test_fts("0.00000000000000000000e+00", 0.0),
+ test_fts("2.50000000000000000000e+01", 25.0),
+ test_fts("2.50000000000000000000e+00", 2.5),
+ test_fts("2.50000000000000000000e-01", 0.25),
+ test_fts("-3.50000000000000000000e+17", -350.0e15),
+ test_fts("1.00000000000000000000e+00",1.0),
+ test_fts("1.00000000000000000000e+00",1.0, []),
+ test_fts("-1.00000000000000000000e+00",-1.0, []),
+ test_fts("-1.00000000000000000000",-1.0, [{decimals, 20}]),
+ {'EXIT', {badarg, _}} = (catch float_to_list(1.0, [{decimals, -1}])),
+ {'EXIT', {badarg, _}} = (catch float_to_list(1.0, [{decimals, 254}])),
+ {'EXIT', {badarg, _}} = (catch float_to_list(1.0, [{scientific, 250}])),
+ {'EXIT', {badarg, _}} = (catch float_to_list(1.0e+300, [{decimals, 1}])),
+ {'EXIT', {badarg, _}} = (catch float_to_binary(1.0, [{decimals, -1}])),
+ {'EXIT', {badarg, _}} = (catch float_to_binary(1.0, [{decimals, 254}])),
+ {'EXIT', {badarg, _}} = (catch float_to_binary(1.0, [{scientific, 250}])),
+ {'EXIT', {badarg, _}} = (catch float_to_binary(1.0e+300, [{decimals, 1}])),
+ test_fts("1.0e+300",1.0e+300, [{scientific, 1}]),
+ test_fts("1.0",1.0, [{decimals, 249}, compact]),
+ test_fts("1",1.0,[{decimals,0}]),
+ test_fts("2",1.9,[{decimals,0}]),
+ test_fts("123456789012345680.0",123456789012345678.0,
+ [{decimals, 236}, compact]),
+ {'EXIT', {badarg, _}} = (catch float_to_list(
+ 123456789012345678.0, [{decimals, 237}])),
+ {'EXIT', {badarg, _}} = (catch float_to_binary(
+ 123456789012345678.0, [{decimals, 237}])),
+ test_fts("1." ++ string:copies("0", 249) ++ "e+00",
+ 1.0, [{scientific, 249}, compact]),
X1 = float_to_list(1.0),
X2 = float_to_list(1.0, [{scientific, 20}]),
X1 = X2,
- "1.000e+00" = float_to_list(1.0, [{scientific, 3}]),
- "1.000" = float_to_list(1.0, [{decimals, 3}]),
- "1.0" = float_to_list(1.0, [{decimals, 1}]),
- "1.0" = float_to_list(1.0, [{decimals, 3}, compact]),
- "1.12" = float_to_list(1.123, [{decimals, 2}]),
- "1.123" = float_to_list(1.123, [{decimals, 3}]),
- "1.123" = float_to_list(1.123, [{decimals, 3}, compact]),
- "1.1230" = float_to_list(1.123, [{decimals, 4}]),
- "1.12300" = float_to_list(1.123, [{decimals, 5}]),
- "1.123" = float_to_list(1.123, [{decimals, 5}, compact]),
- "1.1234" = float_to_list(1.1234,[{decimals, 6}, compact]),
- "1.01" = float_to_list(1.005, [{decimals, 2}]),
- "-1.01" = float_to_list(-1.005,[{decimals, 2}]),
- "0.999" = float_to_list(0.999, [{decimals, 3}]),
- "-0.999" = float_to_list(-0.999,[{decimals, 3}]),
- "1.0" = float_to_list(0.999, [{decimals, 2}, compact]),
- "-1.0" = float_to_list(-0.999,[{decimals, 2}, compact]),
- "0.5" = float_to_list(0.5, [{decimals, 1}]),
- "-0.5" = float_to_list(-0.5, [{decimals, 1}]),
+
+ Y1 = float_to_binary(1.0),
+ Y2 = float_to_binary(1.0, [{scientific, 20}]),
+ Y1 = Y2,
+
+ test_fts("1.000e+00",1.0, [{scientific, 3}]),
+ test_fts("1.000",1.0, [{decimals, 3}]),
+ test_fts("1.0",1.0, [{decimals, 1}]),
+ test_fts("1.0",1.0, [{decimals, 3}, compact]),
+ test_fts("1.12",1.123, [{decimals, 2}]),
+ test_fts("1.123",1.123, [{decimals, 3}]),
+ test_fts("1.123",1.123, [{decimals, 3}, compact]),
+ test_fts("1.1230",1.123, [{decimals, 4}]),
+ test_fts("1.12300",1.123, [{decimals, 5}]),
+ test_fts("1.123",1.123, [{decimals, 5}, compact]),
+ test_fts("1.1234",1.1234,[{decimals, 6}, compact]),
+ test_fts("1.01",1.005, [{decimals, 2}]),
+ test_fts("-1.01",-1.005,[{decimals, 2}]),
+ test_fts("0.999",0.999, [{decimals, 3}]),
+ test_fts("-0.999",-0.999,[{decimals, 3}]),
+ test_fts("1.0",0.999, [{decimals, 2}, compact]),
+ test_fts("-1.0",-0.999,[{decimals, 2}, compact]),
+ test_fts("0.5",0.5, [{decimals, 1}]),
+ test_fts("-0.5",-0.5, [{decimals, 1}]),
"2.333333" = erlang:float_to_list(7/3, [{decimals, 6}, compact]),
"2.333333" = erlang:float_to_list(7/3, [{decimals, 6}]),
- "0.00000000000000000000e+00" = float_to_list(0.0, [compact]),
- "0.0" = float_to_list(0.0, [{decimals, 10}, compact]),
- "123000000000000000000.0" = float_to_list(1.23e20, [{decimals, 10}, compact]),
- "1.2300000000e+20" = float_to_list(1.23e20, [{scientific, 10}, compact]),
- "1.23000000000000000000e+20" = float_to_list(1.23e20, []),
+ <<"2.333333">> = erlang:float_to_binary(7/3, [{decimals, 6}, compact]),
+ <<"2.333333">> = erlang:float_to_binary(7/3, [{decimals, 6}]),
+ test_fts("0.00000000000000000000e+00",0.0, [compact]),
+ test_fts("0.0",0.0, [{decimals, 10}, compact]),
+ test_fts("123000000000000000000.0",1.23e20, [{decimals, 10}, compact]),
+ test_fts("1.2300000000e+20",1.23e20, [{scientific, 10}, compact]),
+ test_fts("1.23000000000000000000e+20",1.23e20, []),
ok.
-test_ftl(Expect, Float) ->
- %% No ?line on the next line -- we want the line number from t_float_to_list.
- Expect = remove_zeros(lists:reverse(float_to_list(Float)), []).
-
-%% Removes any non-significant zeros in a floating point number.
-%% Example: 2.500000e+01 -> 2.5e+1
-
-remove_zeros([$+, $e|Rest], [$0, X|Result]) ->
- remove_zeros([$+, $e|Rest], [X|Result]);
-remove_zeros([$-, $e|Rest], [$0, X|Result]) ->
- remove_zeros([$-, $e|Rest], [X|Result]);
-remove_zeros([$0, $.|Rest], [$e|Result]) ->
- remove_zeros(Rest, [$., $0, $e|Result]);
-remove_zeros([$0|Rest], [$e|Result]) ->
- remove_zeros(Rest, [$e|Result]);
-remove_zeros([Char|Rest], Result) ->
- remove_zeros(Rest, [Char|Result]);
-remove_zeros([], Result) ->
- Result.
+test_fts(Expect, Float) ->
+ Expect = float_to_list(Float),
+ BinExpect = list_to_binary(Expect),
+ BinExpect = float_to_binary(Float).
+
+test_fts(Expect, Float, Args) ->
+ Expect = float_to_list(Float,Args),
+ BinExpect = list_to_binary(Expect),
+ BinExpect = float_to_binary(Float,Args).
+
%% Tests list_to_float/1.
-t_list_to_float_safe(Config) when is_list(Config) ->
- 0.0 = list_to_float(id("0.0")),
- 0.0 = list_to_float(id("-0.0")),
- 0.5 = list_to_float(id("0.5")),
- -0.5 = list_to_float(id("-0.5")),
- 100.0 = list_to_float(id("1.0e2")),
- 127.5 = list_to_float(id("127.5")),
- -199.5 = list_to_float(id("-199.5")),
+t_string_to_float_safe(Config) when is_list(Config) ->
+ test_stf(0.0,"0.0"),
+ test_stf(0.0,"-0.0"),
+ test_stf(0.5,"0.5"),
+ test_stf(-0.5,"-0.5"),
+ test_stf(100.0,"1.0e2"),
+ test_stf(127.5,"127.5"),
+ test_stf(-199.5,"-199.5"),
{'EXIT',{badarg,_}} = (catch list_to_float(id("0"))),
{'EXIT',{badarg,_}} = (catch list_to_float(id("0..0"))),
{'EXIT',{badarg,_}} = (catch list_to_float(id("0e12"))),
{'EXIT',{badarg,_}} = (catch list_to_float(id("--0.0"))),
+ {'EXIT',{badarg,_}} = (catch binary_to_float(id(<<"0">>))),
+ {'EXIT',{badarg,_}} = (catch binary_to_float(id(<<"0..0">>))),
+ {'EXIT',{badarg,_}} = (catch binary_to_float(id(<<"0e12">>))),
+ {'EXIT',{badarg,_}} = (catch binary_to_float(id(<<"--0.0">>))),
+
+ UBin = <<0:3,(id(<<"0.0">>))/binary,0:5>>,
+ <<_:3,UnAlignedBin:3/binary,0:5>> = id(UBin),
+ 0.0 = binary_to_float(UnAlignedBin),
+
+ ABin = <<0:8,(id(<<"1.0">>))/binary,0:8>>,
+ <<_:8,AlignedBin:3/binary,0:8>> = id(ABin),
+ 1.0 = binary_to_float(AlignedBin),
ok.
%% This might crash the emulator...
%% (Known to crash the Unix version of Erlang 4.4.1)
-t_list_to_float_risky(Config) when is_list(Config) ->
+t_string_to_float_risky(Config) when is_list(Config) ->
Many_Ones = lists:duplicate(25000, id($1)),
id(list_to_float("2."++Many_Ones)),
{'EXIT', {badarg, _}} = (catch list_to_float("2"++Many_Ones)),
+
+ id(binary_to_float(list_to_binary("2."++Many_Ones))),
+ {'EXIT', {badarg, _}} = (catch binary_to_float(
+ list_to_binary("2"++Many_Ones))),
ok.
+test_stf(Expect,List) ->
+ Expect = list_to_float(List),
+ Bin = list_to_binary(List),
+ Expect = binary_to_float(Bin).
+
%% Tests round/1.
t_round(Config) when is_list(Config) ->
diff --git a/erts/preloaded/src/erlang.erl b/erts/preloaded/src/erlang.erl
index 744527aeff..8e4a471a82 100644
--- a/erts/preloaded/src/erlang.erl
+++ b/erts/preloaded/src/erlang.erl
@@ -74,7 +74,7 @@
-export([adler32/1, adler32/2, adler32_combine/3, append_element/2]).
-export([atom_to_binary/2, atom_to_list/1, binary_part/2, binary_part/3]).
--export([binary_to_atom/2, binary_to_existing_atom/2]).
+-export([binary_to_atom/2, binary_to_existing_atom/2, binary_to_float/1]).
-export([binary_to_integer/1,binary_to_integer/2]).
-export([binary_to_list/1]).
-export([binary_to_list/3, binary_to_term/1, binary_to_term/2]).
@@ -87,7 +87,8 @@
-export([display_nl/0, display_string/1, dist_exit/3, erase/0, erase/1]).
-export([error/1, error/2, exit/1, exit/2, external_size/1]).
-export([external_size/2, finish_after_on_load/2, finish_loading/1, float/1]).
--export([float_to_list/1, float_to_list/2]).
+-export([float_to_binary/1, float_to_binary/2,
+ float_to_list/1, float_to_list/2]).
-export([fun_info/2, fun_to_list/1, function_exported/3]).
-export([garbage_collect/0, garbage_collect/1]).
-export([garbage_collect_message_area/0, get/0, get/1, get_keys/1]).
@@ -322,6 +323,12 @@ binary_to_atom(_Binary, _Encoding) ->
binary_to_existing_atom(_Binary, _Encoding) ->
erlang:nif_error(undefined).
+%% binary_to_float/1
+-spec binary_to_float(Binary) -> float() when
+ Binary :: binary().
+binary_to_float(_Binary) ->
+ erlang:nif_error(undefined).
+
%% binary_to_integer/1
-spec binary_to_integer(Binary) -> integer() when
Binary :: binary().
@@ -724,6 +731,22 @@ finish_after_on_load(_P1, _P2) ->
float(_Number) ->
erlang:nif_error(undefined).
+%% float_to_binary/1
+-spec float_to_binary(Float) -> binary() when
+ Float :: float().
+float_to_binary(_Float) ->
+ erlang:nif_error(undefined).
+
+%% float_to_binary/2
+-spec float_to_binary(Float, Options) -> binary() when
+ Float :: float(),
+ Options :: [Option],
+ Option :: {decimals, Decimals :: 0..253} |
+ {scientific, Decimals :: 0..249} |
+ compact.
+float_to_binary(_Float, _Options) ->
+ erlang:nif_error(undefined).
+
%% float_to_list/1
-spec float_to_list(Float) -> string() when
Float :: float().
@@ -734,8 +757,8 @@ float_to_list(_Float) ->
-spec float_to_list(Float, Options) -> string() when
Float :: float(),
Options :: [Option],
- Option :: {decimals, non_neg_integer()} |
- {scientific, non_neg_integer()} |
+ Option :: {decimals, Decimals :: 0..253} |
+ {scientific, Decimals :: 0..249} |
compact.
float_to_list(_Float, _Options) ->
erlang:nif_error(undefined).
diff --git a/lib/compiler/src/erl_bifs.erl b/lib/compiler/src/erl_bifs.erl
index 0854ad3a3e..cc07f0b9bc 100644
--- a/lib/compiler/src/erl_bifs.erl
+++ b/lib/compiler/src/erl_bifs.erl
@@ -68,6 +68,7 @@ is_pure(erlang, atom_to_list, 1) -> true;
is_pure(erlang, binary_part, 2) -> true;
is_pure(erlang, binary_part, 3) -> true;
is_pure(erlang, binary_to_atom, 2) -> true;
+is_pure(erlang, binary_to_float, 1) -> true;
is_pure(erlang, binary_to_integer, 1) -> true;
is_pure(erlang, binary_to_list, 1) -> true;
is_pure(erlang, binary_to_list, 3) -> true;
@@ -76,6 +77,7 @@ is_pure(erlang, byte_size, 1) -> true;
is_pure(erlang, element, 2) -> true;
is_pure(erlang, float, 1) -> true;
is_pure(erlang, float_to_list, 1) -> true;
+is_pure(erlang, float_to_binary, 1) -> true;
is_pure(erlang, hash, 2) -> false;
is_pure(erlang, hd, 1) -> true;
is_pure(erlang, integer_to_binary, 1) -> true;
diff --git a/lib/stdlib/src/erl_internal.erl b/lib/stdlib/src/erl_internal.erl
index 79a06c9bec..378e629ac9 100644
--- a/lib/stdlib/src/erl_internal.erl
+++ b/lib/stdlib/src/erl_internal.erl
@@ -256,6 +256,7 @@ bif(binary_to_atom, 2) -> true;
bif(binary_to_existing_atom, 2) -> true;
bif(binary_to_integer, 1) -> true;
bif(binary_to_integer, 2) -> true;
+bif(binary_to_float, 1) -> true;
bif(binary_to_list, 1) -> true;
bif(binary_to_list, 3) -> true;
bif(binary_to_term, 1) -> true;
@@ -281,6 +282,8 @@ bif(exit, 2) -> true;
bif(float, 1) -> true;
bif(float_to_list, 1) -> true;
bif(float_to_list, 2) -> true;
+bif(float_to_binary, 1) -> true;
+bif(float_to_binary, 2) -> true;
bif(garbage_collect, 0) -> true;
bif(garbage_collect, 1) -> true;
bif(get, 0) -> true;
diff --git a/lib/tools/emacs/erlang.el b/lib/tools/emacs/erlang.el
index 5139d6f6ff..ddd22707dd 100644
--- a/lib/tools/emacs/erlang.el
+++ b/lib/tools/emacs/erlang.el
@@ -728,6 +728,7 @@ resulting regexp is surrounded by \\_< and \\_>."
"atom_to_list"
"binary_to_atom"
"binary_to_existing_atom"
+ "binary_to_float"
"binary_to_integer"
"binary_to_list"
"binary_to_term"
@@ -747,6 +748,7 @@ resulting regexp is surrounded by \\_< and \\_>."
"error"
"exit"
"float"
+ "float_to_binary"
"float_to_list"
"garbage_collect"
"get"
diff --git a/system/doc/reference_manual/data_types.xml b/system/doc/reference_manual/data_types.xml
index 1eac575df7..73ec6e2b82 100644
--- a/system/doc/reference_manual/data_types.xml
+++ b/system/doc/reference_manual/data_types.xml
@@ -397,7 +397,11 @@ hello
14> <input>binary_to_integer(&lt;&lt;"77">>).</input>
77
15> <input>integer_to_binary(77).</input>
-&lt;&lt;"77">></pre>
+&lt;&lt;"77">>
+16> <input>float_to_binary(7.0).</input>
+&lt;&lt;"7.00000000000000000000e+00">>
+17> <input>binary_to_float(&lt;&lt;"7.000e+00>>").</input>
+7.0</pre>
</section>
</chapter>