Fix int overflows in Float::to_precision with a high float value
or a high precision.
The native implementation was removed by
9cb09ccf to support the
interpreter, which, at the time, did not support the FFI. Since then, we
added support for thhe FFI in the interpreter.
Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>
- if decimals == 0 then return self.to_i.to_s
- var f = self
- for i in [0..decimals[ do f = f * 10.0
- if self > 0.0 then
- f = f + 0.5
- else
- f = f - 0.5
- end
- var i = f.to_i
- if i == 0 then return "0." + "0"*decimals
-
- # Prepare both parts of the float, before and after the "."
- var s = i.abs.to_s
- var sl = s.length
- var p1
- var p2
- if sl > decimals then
- # Has something before the "."
- p1 = s.substring(0, sl-decimals)
- p2 = s.substring(sl-decimals, decimals)
- else
- p1 = "0"
- p2 = "0"*(decimals-sl) + s
- end
+ var size = to_precision_size(decimals)
+ var cstr = new CString(size+1)
+ to_precision_fill(decimals, size+1, cstr)
+ return cstr.to_s_unsafe(byte_length=size, copy=false)
+ end
- if i < 0 then p1 = "-" + p1
+ # Required string length to hold `self` with `nb` decimals
+ #
+ # The length does not include the terminating null byte.
+ private fun to_precision_size(nb: Int): Int `{
+ return snprintf(NULL, 0, "%.*f", (int)nb, self);
+ `}
- return p1 + "." + p2
- end
+ # Fill `cstr` with `self` and `nb` decimals
+ private fun to_precision_fill(nb, size: Int, cstr: CString) `{
+ snprintf(cstr, size, "%.*f", (int)nb, self);
+ `}
1 1 0.0000000000000000 1
2 1 0.0000000000000000 0
3 2 1.0000000000000000 01
1 1 0.0000000000000000 1
2 1 0.0000000000000000 0
3 2 1.0000000000000000 01
-4 3 0.9182958340544894 010
+4 3 0.9182958340544896 010
5 5 0.9709505944546686 01001
5 5 0.9709505944546686 01001
-6 8 0.9544340029249650 01001010
+6 8 0.9544340029249649 01001010
7 13 0.9612366047228760 0100101001001
7 13 0.9612366047228760 0100101001001
-8 21 0.9587118829771316 010010100100101001010
-9 34 0.9596868937742170 0100101001001010010100100101001001
-10 55 0.9593160320543778 ...
+8 21 0.9587118829771318 010010100100101001010
+9 34 0.9596868937742169 0100101001001010010100100101001001
+10 55 0.9593160320543777 ...
11 89 0.9594579158386696 ...
11 89 0.9594579158386696 ...
-12 144 0.9594037542210228 ...
-13 233 0.9594244469559864 ...
-14 377 0.9594165437404406 ...
-15 610 0.9594195626031440 ...
-16 987 0.9594184095152248 ...
-17 1597 0.9594188499578102 ...
-18 2584 0.9594186817240320 ...
+12 144 0.9594037542210230 ...
+13 233 0.9594244469559867 ...
+14 377 0.9594165437404407 ...
+15 610 0.9594195626031441 ...
+16 987 0.9594184095152245 ...
+17 1597 0.9594188499578099 ...
+18 2584 0.9594186817240321 ...
19 4181 0.9594187459836638 ...
19 4181 0.9594187459836638 ...
-20 6765 0.9594187214386752 ...
-21 10946 0.9594187308140276 ...
-22 17711 0.9594187272329618 ...
-23 28657 0.9594187286008076 ...
-24 46368 0.9594187280783368 ...
-25 75025 0.9594187282779028 ...
-26 121393 0.9594187282016752 ...
-27 196418 0.9594187282307916 ...
+20 6765 0.9594187214386756 ...
+21 10946 0.9594187308140278 ...
+22 17711 0.9594187272329620 ...
+23 28657 0.9594187286008073 ...
+24 46368 0.9594187280783371 ...
+25 75025 0.9594187282779029 ...
+26 121393 0.9594187282016755 ...
+27 196418 0.9594187282307918 ...
28 317811 0.9594187282196702 ...
28 317811 0.9594187282196702 ...
-29 514229 0.9594187282239182 ...
-30 832040 0.9594187282222962 ...
+29 514229 0.9594187282239184 ...
+30 832040 0.9594187282222959 ...
31 1346269 0.9594187282229156 ...
31 1346269 0.9594187282229156 ...
-32 2178309 0.9594187282226794 ...
-33 3524578 0.9594187282227690 ...
-34 5702887 0.9594187282227344 ...
-35 9227465 0.9594187282227478 ...
-36 14930352 0.9594187282227430 ...
+32 2178309 0.9594187282226789 ...
+33 3524578 0.9594187282227691 ...
+34 5702887 0.9594187282227347 ...
+35 9227465 0.9594187282227479 ...
+36 14930352 0.9594187282227429 ...
37 24157817 0.9594187282227448 ...
37 24157817 0.9594187282227448 ...
i=64 h=45 p=2.812500
i=128 h=95 p=2.968750
i=256 h=197 p=3.078125
i=64 h=45 p=2.812500
i=128 h=95 p=2.968750
i=256 h=197 p=3.078125
test_attr_easy.nit:20,5--16: Warning: expression is already a `String`.
test_attr_easy.nit:20,20--26: Warning: expression is already a `B`.
test_attr_easy.nit:20,44--63: Warning: expression is already a `HashMap[Int, B]`.
test_attr_easy.nit:20,5--16: Warning: expression is already a `String`.
test_attr_easy.nit:20,20--26: Warning: expression is already a `B`.
test_attr_easy.nit:20,44--63: Warning: expression is already a `HashMap[Int, B]`.
-true false 12345 1.235 asdf true
+true false 12345 1.234 asdf true
an instance of B
true true true true
true true true true
an instance of B
true true true true
true true true true