flt 1.4.4 → 1.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/History.txt +5 -0
- data/lib/flt/num.rb +144 -87
- data/lib/flt/version.rb +1 -1
- data/test/test_format.rb +80 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7de71640b6e679c521d717895549d5858393bf9a
|
4
|
+
data.tar.gz: 20405872b9008205ffd8f4af67b2197be583539f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d5b4929799d05f048bf51827ad8dd3704467d71e4d93b996e3841c2a85d098770b20f70a7dd75b1dd86d4975d05c1232a9669e826eea70370f03e93dd61ccca6
|
7
|
+
data.tar.gz: a4f6ee9f59a5e6c70c128f902465927bd68a07858871a6dff468fa78a5615d5048e6c2e4302210b60ca749b1d54dabc8175220ec617fb888e7cbba1517b68791
|
data/History.txt
CHANGED
data/lib/flt/num.rb
CHANGED
@@ -3192,64 +3192,9 @@ class Num < Numeric
|
|
3192
3192
|
return product.add(third, context)
|
3193
3193
|
end
|
3194
3194
|
|
3195
|
-
#
|
3196
|
-
#
|
3197
|
-
# If the output base is the floating-point radix, the rendered value is the exact value of the number,
|
3198
|
-
# showing trailing zeros up to the stored precision.
|
3199
|
-
#
|
3200
|
-
# With bases different from the radix, the floating-point number is treated
|
3201
|
-
# as an approximation with a precision of number_of_digits, representing any value
|
3202
|
-
# within its rounding range. In that case, this method always renders
|
3203
|
-
# that aproximated value in other base without introducing additional precision.
|
3204
|
-
#
|
3205
|
-
# The resulting text numeral is such that it has as few digits as possible while
|
3206
|
-
# preserving the original while if converted back to the same type of floating-point value with
|
3207
|
-
# the same context precision that the original number had (number_of_digits).
|
3208
|
-
#
|
3209
|
-
# To render the exact value of a Num x in a different base b this can be used
|
3210
|
-
# Flt::Num.convert_exact(x, b).to_s(:base=>b)
|
3211
|
-
# Or, to represent a BinNum x in decimal:
|
3212
|
-
# x.to_decimal_exact(:exact=>true).to_s
|
3213
|
-
#
|
3214
|
-
# Options:
|
3215
|
-
# :base output base, 10 by default
|
3216
|
-
#
|
3217
|
-
# :rounding is used to override the context rounding, but it's main use is specify :nearest
|
3218
|
-
# as the rounding-mode, which means that the text literal will have enough digits to be
|
3219
|
-
# converted back to self in any round-to_nearest rounding mode. Otherwise only enough
|
3220
|
-
# digits for conversion in a specific rounding mode are produced.
|
3221
|
-
#
|
3222
|
-
# :all_digits if true all significant digits are shown. A digit
|
3223
|
-
# is considered as significant here if when used on input, cannot
|
3224
|
-
# arbitrarily change its value and preserve the parsed value of the
|
3225
|
-
# floating point number.
|
3226
|
-
# Using all_digits will show trailing zeros up to the precision of the floating-point, so
|
3227
|
-
# the output will preserve the input precision. With all_digits and the :down rounding-mod
|
3228
|
-
# (truncation), the result will be the exact value floating-point value in the output base
|
3229
|
-
# (if it is conmensurable with the floating-point base).
|
3195
|
+
# Representation as text of a number: this is an alias of Num#format
|
3230
3196
|
def to_s(*args)
|
3231
|
-
|
3232
|
-
context=nil
|
3233
|
-
|
3234
|
-
# admit legacy arguments eng, context in that order
|
3235
|
-
if [true,false].include?(args.first)
|
3236
|
-
eng = args.shift
|
3237
|
-
end
|
3238
|
-
if args.first.is_a?(Num::ContextBase)
|
3239
|
-
context = args.shift
|
3240
|
-
end
|
3241
|
-
# admit also :eng to specify the eng mode
|
3242
|
-
if args.first == :eng
|
3243
|
-
eng = true
|
3244
|
-
args.shift
|
3245
|
-
end
|
3246
|
-
raise TypeError, "Invalid arguments to #{num_class}#to_s" if args.size>1 || (args.size==1 && !args.first.is_a?(Hash))
|
3247
|
-
# an admit arguments through a final parameters Hash
|
3248
|
-
options = args.first || {}
|
3249
|
-
context = options.delete(:context) if options.has_key?(:context)
|
3250
|
-
eng = options.delete(:eng) if options.has_key?(:eng)
|
3251
|
-
|
3252
|
-
format(context, options.merge(:eng=>eng))
|
3197
|
+
format *args
|
3253
3198
|
end
|
3254
3199
|
|
3255
3200
|
# Raises to the power of x, to modulo if given.
|
@@ -3754,42 +3699,133 @@ class Num < Numeric
|
|
3754
3699
|
|
3755
3700
|
end
|
3756
3701
|
|
3757
|
-
#
|
3758
|
-
#
|
3759
|
-
|
3760
|
-
|
3702
|
+
# Internal method to allow format (and to_s) to admit legacy
|
3703
|
+
# parameters.
|
3704
|
+
def format_legacy_parameters(*args)
|
3705
|
+
eng = false
|
3706
|
+
context = nil
|
3707
|
+
|
3708
|
+
# formerly the eng value and the context could be passed
|
3709
|
+
# as separate values in that order
|
3710
|
+
if [true,false].include?(args.first)
|
3711
|
+
eng = args.shift
|
3712
|
+
end
|
3713
|
+
if args.first.is_a?(Num::ContextBase)
|
3714
|
+
context = args.shift
|
3715
|
+
end
|
3716
|
+
|
3717
|
+
# and the :eng symbol could be passed to enable it
|
3718
|
+
if args.first == :eng
|
3719
|
+
eng = true
|
3720
|
+
args.shift
|
3721
|
+
end
|
3722
|
+
|
3723
|
+
if args.size > 1 || (args.size == 1 && !args.first.is_a?(Hash))
|
3724
|
+
raise TypeError, "Invalid arguments to #{num_class}#format"
|
3725
|
+
end
|
3726
|
+
|
3727
|
+
# now all arguments should be passed in a hash
|
3728
|
+
options = args.first || {}
|
3729
|
+
{ :eng => eng, :context => context }.merge(options)
|
3730
|
+
end
|
3731
|
+
private :format_legacy_parameters
|
3732
|
+
|
3733
|
+
# Conversion to a text literal
|
3761
3734
|
#
|
3762
|
-
#
|
3763
|
-
#
|
3735
|
+
# The base of the produced literal can be specified by the :base option,
|
3736
|
+
# which is 10 by default.
|
3764
3737
|
#
|
3765
|
-
#
|
3766
|
-
# as the rounding-mode, which means that the text literal will have enough digits to be
|
3767
|
-
# converted back to self in any round-to_nearest rounding mode. Otherwise only enough
|
3768
|
-
# digits for conversion in a specific rounding mode are produced.
|
3738
|
+
# ## Same base
|
3769
3739
|
#
|
3770
|
-
#
|
3771
|
-
# is
|
3740
|
+
# If the output base is the floating-point radix the actual internal value
|
3741
|
+
# of the number is produced, by default showing trailing zeros up to the
|
3742
|
+
# stored precision, e.g. 0.100.
|
3743
|
+
#
|
3744
|
+
# The :simplified option can be used in this case to remove the trailing
|
3745
|
+
# zeros, producing 0.1. The actual effect of this options is to regard
|
3746
|
+
# the number an *approximation* (see below) and show only as few digits
|
3747
|
+
# as possible while making sure that the result rounds back to the original
|
3748
|
+
# value (if rounded to its original precision).
|
3749
|
+
#
|
3750
|
+
# With the :all_digits option the number will be considered also an
|
3751
|
+
# approximation and all its 'significant' digits are shown. A digit
|
3752
|
+
# is considered significant here if when used on input, cannot
|
3772
3753
|
# arbitrarily change its value and preserve the parsed value of the
|
3773
|
-
# floating point number.
|
3754
|
+
# floating point number (to the original precision).
|
3755
|
+
# In our case the result would be 0.1000, because the additional shown 0
|
3756
|
+
# is a digit that if changed arbitrarily could make the number round to
|
3757
|
+
# a different value from the original 0.100.
|
3758
|
+
#
|
3759
|
+
# ## Different bases
|
3760
|
+
#
|
3761
|
+
# For bases different from the radix, by default the floating-point number
|
3762
|
+
# is treated as an approximation and is redendered as if with the
|
3763
|
+
# :simplified option mention above.
|
3764
|
+
#
|
3765
|
+
# The :all_digits option acts as in the same-base case. Note that
|
3766
|
+
# aproximated values are formatted without introducing additional precision.
|
3767
|
+
#
|
3768
|
+
# The :exact options can be used to render the exact value in the output
|
3769
|
+
# base (by using Flt::Num.convert_exact)
|
3770
|
+
#
|
3771
|
+
# ## All available options:
|
3772
|
+
#
|
3773
|
+
# :base defines the output base, 10 by default. If the output base is defined
|
3774
|
+
# as :hex_bin, then the %A/%a format of printf is used, which shows the
|
3775
|
+
# significand as an hexadecimal number and the binary exponent in decimal.
|
3774
3776
|
#
|
3775
|
-
# :
|
3776
|
-
#
|
3777
|
-
#
|
3778
|
-
# will be used.
|
3777
|
+
# :exp_base allows to define a different base for the exponent
|
3778
|
+
# than for the coefficient, as occurs with the :hex_bin base; the base for the
|
3779
|
+
# coefficient must be a power of that of the exponent.
|
3779
3780
|
#
|
3780
|
-
#
|
3781
|
-
#
|
3782
|
-
#
|
3783
|
-
#
|
3781
|
+
# :rounding is used to override the context rounding. It allows to
|
3782
|
+
# specify the :nearest as the rounding-mode, which means that the text
|
3783
|
+
# literal will have enough digits to be converted back to the original value
|
3784
|
+
# in any of the round-to-nearest rounding modes. Otherwise only enough
|
3785
|
+
# digits for conversion in a specific rounding mode are produced.
|
3786
|
+
#
|
3787
|
+
# :all_digits makes all 'significant' digits visible, considering
|
3788
|
+
# the number approximate as explained below.
|
3789
|
+
# Using :all_digits will show trailing zeros up to the precision of the
|
3790
|
+
# floating-point, so the output will preserve the input precision.
|
3791
|
+
# With :all_digits and the :down rounding-mode (truncation), the result will
|
3792
|
+
# be the exact value floating-point value in the output base
|
3793
|
+
# (if it is conmensurable with the floating-point radix).
|
3794
|
+
#
|
3795
|
+
# :simplify shows only the digits necessary to preserve the original value
|
3796
|
+
# (which is the default when output base differs from radix)
|
3797
|
+
#
|
3798
|
+
# :exact interprets the number as an exact value, not an approximation so
|
3799
|
+
# that the exact original value can be rendered in a different base.
|
3784
3800
|
#
|
3785
|
-
#
|
3786
|
-
# the Flt an exact number), this can be done with Num.convert_exact.
|
3801
|
+
# :format specifies the numeric format:
|
3787
3802
|
#
|
3788
|
-
#
|
3789
|
-
#
|
3803
|
+
# * :sci selects scientific notation
|
3804
|
+
# * :fix selects fixed format (no exponent is shown)
|
3805
|
+
# * :eng is equivalent to :sci and setting the :eng option
|
3806
|
+
# * :auto selects :fix or :sci automatically (the default)
|
3790
3807
|
#
|
3791
|
-
|
3792
|
-
|
3808
|
+
# ## Note: approximate vs exact values
|
3809
|
+
#
|
3810
|
+
# In order to represent a floating point value `x`, we can take
|
3811
|
+
# two approaches:
|
3812
|
+
#
|
3813
|
+
# * Consider it an *exact* value, namely:
|
3814
|
+
# `x.sign*x.integral_significand*radix**x.integral_exponent`
|
3815
|
+
# * Consider it an *approximation* with its particular precision,
|
3816
|
+
# that represents any value within its rounding range.
|
3817
|
+
# The exact rounding range depends on the rounding mode used to create
|
3818
|
+
# the floating point mode; in the case of nearest rounding it is the
|
3819
|
+
# set of numbers that line closer to the floating point value than to
|
3820
|
+
# any other floating point value.
|
3821
|
+
#
|
3822
|
+
def format(*args)
|
3823
|
+
options = format_legacy_parameters(*args)
|
3824
|
+
|
3825
|
+
format_mode = options[:format] || :auto
|
3826
|
+
max_leading_zeros = 6
|
3827
|
+
|
3828
|
+
num_context = options[:context]
|
3793
3829
|
output_radix = options[:base] || 10
|
3794
3830
|
output_exp_radix = options[:exp_base]
|
3795
3831
|
if output_radix == :hex_bin
|
@@ -3801,7 +3837,13 @@ class Num < Numeric
|
|
3801
3837
|
rounding = options[:rounding]
|
3802
3838
|
all_digits = options[:all_digits]
|
3803
3839
|
eng = options[:eng]
|
3840
|
+
if format_mode == :eng
|
3841
|
+
format_mode = :sci
|
3842
|
+
eng = true
|
3843
|
+
end
|
3804
3844
|
output_rounding = options[:output_rounding]
|
3845
|
+
exact = options[:exact]
|
3846
|
+
simplified = options[:simplified]
|
3805
3847
|
all_digits ||= output_rounding
|
3806
3848
|
|
3807
3849
|
sgn = @sign<0 ? '-' : ''
|
@@ -3827,6 +3869,13 @@ class Num < Numeric
|
|
3827
3869
|
end
|
3828
3870
|
end
|
3829
3871
|
|
3872
|
+
if output_radix != num_class.radix && exact && !all_digits && !simplified
|
3873
|
+
value = Num[output_radix].context(exact: true){ Num.convert_exact(self, output_radix) }
|
3874
|
+
options = options.dup
|
3875
|
+
options.delete :context
|
3876
|
+
return value.format(options)
|
3877
|
+
end
|
3878
|
+
|
3830
3879
|
if output_exp_radix == num_class.radix && !all_digits && output_radix != output_exp_radix
|
3831
3880
|
if first_digit_1
|
3832
3881
|
# make the first digit a 1
|
@@ -3847,7 +3896,7 @@ class Num < Numeric
|
|
3847
3896
|
n_ds = ds.size
|
3848
3897
|
leftdigits = exp + n_ds
|
3849
3898
|
exp_radix = num_class.radix
|
3850
|
-
elsif output_radix == num_class.radix && !all_digits && output_radix == output_exp_radix
|
3899
|
+
elsif output_radix == num_class.radix && !all_digits && output_radix == output_exp_radix && !simplified
|
3851
3900
|
# show exactly inner representation and precision
|
3852
3901
|
ds = @coeff.to_s(output_radix)
|
3853
3902
|
n_ds = ds.size
|
@@ -3898,8 +3947,16 @@ class Num < Numeric
|
|
3898
3947
|
n_ds = ds.size
|
3899
3948
|
end
|
3900
3949
|
else
|
3901
|
-
|
3902
|
-
|
3950
|
+
if format_mode == :auto
|
3951
|
+
fix = exp <= 0
|
3952
|
+
fix &&= leftdigits > -max_leading_zeros if max_leading_zeros
|
3953
|
+
if fix
|
3954
|
+
format_mode = :fix
|
3955
|
+
else
|
3956
|
+
format_mode = :sci
|
3957
|
+
end
|
3958
|
+
end
|
3959
|
+
if format_mode == :fix
|
3903
3960
|
dotplace = leftdigits
|
3904
3961
|
elsif !eng
|
3905
3962
|
dotplace = 1
|
data/lib/flt/version.rb
CHANGED
data/test/test_format.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__),'helper.rb'))
|
2
|
+
|
3
|
+
class TestFormat < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
initialize_context
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_same_base_format
|
10
|
+
value = DecNum('0.100', :free)
|
11
|
+
assert_equal '0.100', value.to_s
|
12
|
+
assert_equal '0.1', value.to_s(:simplified => true)
|
13
|
+
assert_equal '0.1000', value.to_s(:all_digits => true)
|
14
|
+
|
15
|
+
value = DecNum('1.00', :free)
|
16
|
+
assert_equal '1.00', value.to_s
|
17
|
+
assert_equal '1', value.to_s(:simplified => true)
|
18
|
+
assert_equal '1.000', value.to_s(:all_digits => true)
|
19
|
+
|
20
|
+
value = DecNum('0.101', :free)
|
21
|
+
assert_equal '0.101', value.to_s
|
22
|
+
assert_equal '0.101', value.to_s(:simplified => true)
|
23
|
+
assert_equal '0.1010', value.to_s(:all_digits => true)
|
24
|
+
|
25
|
+
value = DecNum('0.100', :free)
|
26
|
+
assert_equal '0.100', value.to_s
|
27
|
+
assert_equal '0.1', value.to_s(:simplified => true)
|
28
|
+
assert_equal '0.1000', value.to_s(:all_digits => true)
|
29
|
+
|
30
|
+
value = DecNum('0.100E-10', :free)
|
31
|
+
assert_equal '1.00E-11', value.to_s
|
32
|
+
assert_equal '1E-11', value.to_s(:simplified => true)
|
33
|
+
assert_equal '1.000E-11', value.to_s(:all_digits => true)
|
34
|
+
|
35
|
+
value = DecNum('0.100E+10', :free)
|
36
|
+
assert_equal '1.00E+9', value.to_s
|
37
|
+
assert_equal '1E+9', value.to_s(:simplified => true)
|
38
|
+
assert_equal '1.000E+9', value.to_s(:all_digits => true)
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_mixed_base_format
|
42
|
+
value = BinNum.context(precision: 6){ BinNum('0.1', :fixed)}
|
43
|
+
assert_equal '0.099609375', value.to_s(:exact => true)
|
44
|
+
assert_equal '0.1', value.to_s
|
45
|
+
assert_equal '0.100', value.to_s(:all_digits => true)
|
46
|
+
assert_equal '0.099609375', value.to_s(:all_digits => true, :rounding => :down)
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_sci_format
|
50
|
+
assert_equal '1.23E-3', DecNum('0.00123').to_s(format: :sci)
|
51
|
+
assert_equal '1.23E-6', DecNum('0.00000123').to_s(format: :sci)
|
52
|
+
assert_equal '1.23E-9', DecNum('0.00000000123').to_s(format: :sci)
|
53
|
+
assert_equal '1.23E-12', DecNum('0.00000000000123').to_s(format: :sci)
|
54
|
+
n = 1000
|
55
|
+
assert_equal "1.23E#{-n+2}", DecNum("123E-#{n}").to_s(format: :sci)
|
56
|
+
assert_equal "1.23E+#{n+2}", DecNum("123E#{n}").to_s(format: :sci)
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_fix_format
|
60
|
+
assert_equal '0.00123', DecNum('0.00123').to_s(format: :fix)
|
61
|
+
assert_equal '0.00000123', DecNum('0.00000123').to_s(format: :fix)
|
62
|
+
assert_equal '0.00000000123', DecNum('0.00000000123').to_s(format: :fix)
|
63
|
+
assert_equal '0.00000000000123', DecNum('0.00000000000123').to_s(format: :fix)
|
64
|
+
n = 1000
|
65
|
+
assert_equal '0.'+'0'*(n-3)+'123', DecNum("123E-#{n}").to_s(format: :fix)
|
66
|
+
assert_equal '123'+'0'*n, DecNum("123E#{n}").to_s(format: :fix)
|
67
|
+
end
|
68
|
+
|
69
|
+
def test_auto_format
|
70
|
+
assert_equal '0.00123', DecNum('0.00123').to_s(format: :auto)
|
71
|
+
assert_equal '0.00000123', DecNum('0.00000123').to_s(format: :auto)
|
72
|
+
assert_equal '1.23E-7', DecNum('0.000000123').to_s(format: :auto)
|
73
|
+
assert_equal '1.23E-9', DecNum('0.00000000123').to_s(format: :auto)
|
74
|
+
assert_equal '1.23E-12', DecNum('0.00000000000123').to_s(format: :auto)
|
75
|
+
n = 1000
|
76
|
+
assert_equal "1.23E#{-n+2}", DecNum("123E-#{n}").to_s(format: :auto)
|
77
|
+
assert_equal "1.23E+#{n+2}", DecNum("123E#{n}").to_s(format: :auto)
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.4.
|
4
|
+
version: 1.4.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Javier Goizueta
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-03-
|
11
|
+
date: 2015-03-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -93,6 +93,7 @@ files:
|
|
93
93
|
- test/test_epsilon.rb
|
94
94
|
- test/test_exact.rb
|
95
95
|
- test/test_flags.rb
|
96
|
+
- test/test_format.rb
|
96
97
|
- test/test_formatter.rb
|
97
98
|
- test/test_hex_format.rb
|
98
99
|
- test/test_multithreading.rb
|
@@ -148,6 +149,7 @@ test_files:
|
|
148
149
|
- test/test_epsilon.rb
|
149
150
|
- test/test_exact.rb
|
150
151
|
- test/test_flags.rb
|
152
|
+
- test/test_format.rb
|
151
153
|
- test/test_formatter.rb
|
152
154
|
- test/test_hex_format.rb
|
153
155
|
- test/test_multithreading.rb
|