flt 1.4.4 → 1.4.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|