forked from fixin.me/fixin.me
Change Unit.multiplier type from decimal to float
Remove remnants related to BigDecimal.
This commit is contained in:
@@ -1,19 +0,0 @@
|
||||
module CoreExt::ActiveModel::Validations::NumericalityValidatesPrecisionAndScale
|
||||
def validate_each(record, attr_name, value, ...)
|
||||
super(record, attr_name, value, ...)
|
||||
|
||||
if options[:precision] || options[:scale]
|
||||
attr_type = record.class.type_for_attribute(attr_name)
|
||||
# For conversion of 'value' to BigDecimal 'ndigits' is not supplied intentionally,
|
||||
# to avoid silent rounding. It is only required for conversion from Float and
|
||||
# Rational, which should not happen.
|
||||
value = BigDecimal(value) unless value.is_a? BigDecimal
|
||||
if options[:precision] && (value.precision > attr_type.precision)
|
||||
record.errors.add(attr_name, :precision_exceeded, **filtered_options(attr_type.precision))
|
||||
end
|
||||
if options[:scale] && (value.scale > attr_type.scale)
|
||||
record.errors.add(attr_name, :scale_exceeded, **filtered_options(attr_type.scale))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,36 +0,0 @@
|
||||
module CoreExt
|
||||
module BigDecimalScientificNotation
|
||||
def to_scientific
|
||||
return 'NaN' unless finite?
|
||||
|
||||
sign, coefficient, base, exponent = split
|
||||
(sign == -1 ? '-' : '') +
|
||||
(coefficient.length > 1 ? coefficient.insert(1, '.') : coefficient) +
|
||||
(exponent != 1 ? "e#{exponent-1}" : '')
|
||||
end
|
||||
|
||||
# Converts value to HTML formatted scientific notation
|
||||
def to_html
|
||||
sign, coefficient, base, exponent = split
|
||||
return 'NaN' unless sign
|
||||
|
||||
result = (sign == -1 ? '-' : '')
|
||||
unless coefficient == '1' && sign == 1
|
||||
if coefficient.length > 1
|
||||
result += coefficient.insert(1, '.')
|
||||
elsif
|
||||
result += coefficient
|
||||
end
|
||||
if exponent != 1
|
||||
result += "×"
|
||||
end
|
||||
end
|
||||
if exponent != 1
|
||||
result += "10<sup>% d</sup>" % [exponent-1]
|
||||
end
|
||||
result.html_safe
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
BigDecimal.prepend CoreExt::BigDecimalScientificNotation
|
||||
54
lib/core_ext/float.rb
Normal file
54
lib/core_ext/float.rb
Normal file
@@ -0,0 +1,54 @@
|
||||
# If a decimal string with at most 15 significant digits is converted to the
|
||||
# IEEE 754 double-precision format, giving a normal number, and then converted
|
||||
# back to a decimal string with the same number of digits, the final result
|
||||
# should match the original string.
|
||||
# If an IEEE 754 double-precision number is converted to a decimal string with
|
||||
# at least 17 significant digits, and then converted back to double-precision
|
||||
# representation, the final result must match the original number:
|
||||
# ("%.16e" % self).to_f == self
|
||||
class Float
|
||||
def to_scientific
|
||||
sign, significand, exponent = split
|
||||
sign + significand + (exponent != 0 ? "e#{exponent}" : '')
|
||||
end
|
||||
|
||||
# Converts value to HTML formatted scientific notation.
|
||||
def to_html(show_unity: true)
|
||||
result, significand, exponent = split
|
||||
result += significand if significand != '1' || (exponent == 0 && show_unity)
|
||||
if exponent != 0
|
||||
result += "×" if significand != '1'
|
||||
result += "10<sup>% d</sup>" % exponent
|
||||
end
|
||||
result.html_safe
|
||||
end
|
||||
|
||||
# Assume #finite? is true.
|
||||
def limit(precision = DIG)
|
||||
return 0.0 if precision.zero?
|
||||
sign, significand, exponent = split(DIG_MAX)
|
||||
"#{sign}#{significand[..precision]}e#{exponent}".to_f
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
SPLIT_FLOAT = /(-?)(.*?)\.?0*e(.*)/
|
||||
|
||||
# Format `%e` displays starting from significant digit (not 0).
|
||||
def split(digits = DIG)
|
||||
return ['', to_s[..2], 0] unless finite?
|
||||
return ['', '0', 0] if digits.zero?
|
||||
("%.#{digits - 1}e" % self).match(SPLIT_FLOAT).captures
|
||||
.then { |sign, significand, exponent| [sign, significand, exponent.to_i] }
|
||||
end
|
||||
|
||||
# The maximum number of significant decimal digits in a double-precision
|
||||
# floating point number.
|
||||
DIG_MAX = 17
|
||||
# Smallest and largest double-precision floating point numbers with DIG
|
||||
# precision.
|
||||
# TODO: change MIN_15 to MIN.ceil(MIN_10_EXP - DIG) after #ceil fix in Ruby
|
||||
# v4.0.5: https://bugs.ruby-lang.org/issues/22079
|
||||
MIN_15 = MIN.ceil(-(MIN_10_EXP - 1))
|
||||
MAX_15 = MAX.floor(-(MAX_10_EXP - DIG + 1))
|
||||
end
|
||||
31
lib/core_ext/range.rb
Normal file
31
lib/core_ext/range.rb
Normal file
@@ -0,0 +1,31 @@
|
||||
class Range
|
||||
# TODO: cleanup comments after commit
|
||||
# * < nil, true < false
|
||||
#if a.end == b.end
|
||||
# a.exclude_end? ^ b.exclude_end? ? (a.exclude_end? ? -1 : 1) : 0
|
||||
#else
|
||||
# a.end <=> b.end || (a.end.nil? ? 1 : -1)
|
||||
#end
|
||||
#a.end == b.end ? (b.exclude_end? ? b : a) : [a, b].to_h.except(nil).min
|
||||
#*(l[0] == r[0] ? (r[1] ? r : l) : [l, r].reject{ |e| e[0].nil? }.min)
|
||||
def &(other)
|
||||
case other
|
||||
when Range
|
||||
return nil unless self.overlap?(other)
|
||||
|
||||
both = [self, other]
|
||||
return Range.new(
|
||||
both.map(&:begin).compact.max,
|
||||
*if self.end == other.end
|
||||
other.exclude_end? ? [other] : [self]
|
||||
else
|
||||
both.select(&:end)
|
||||
end.map { |r| [r.end, r.exclude_end?] }.min
|
||||
)
|
||||
when Array
|
||||
return other.map { |o| self & o }.compact
|
||||
else
|
||||
return self.member?(other) ? other : nil
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user