سؤال

في روبي، أريد أن تحويل عدد عشري إلى int اذا كان عدد صحيح. على سبيل المثال

a = 1.0
b = 2.5

a.to_int_if_whole # => 1
b.to_int_if_whole # => 2.5

وأساسا أنا أحاول تجنب عرض "0.0" على أي عدد ليس لديها عشري. أنا أبحث عن وسيلة أنيقة (أو المدمج في) للقيام

def to_int_if_whole(float)
  (float % 1 == 0) ? float.to_i : float
end
هل كانت مفيدة؟

المحلول 3

وهذا هو الحل الذي انتهى العمل بالطريقة التي أريدها أن:

class Float
  alias_method(:original_to_s, :to_s) unless method_defined?(:original_to_s)

  def is_whole?
    self % 1 == 0
  end

  def to_s
    self.is_whole? ? self.to_i.to_s : self.original_to_s
  end
end

وبهذه الطريقة يمكنني تحديث منطق is_whole? (I يبدو تادمان هو الأكثر تطورا) إذا لزم الأمر، وأنه يضمن أن أي مكان على مخرجات تعويم إلى سلسلة (على سبيل المثال، في شكل) يبدو بالطريقة التي أريدها ل (أي لا الأصفار في نهاية).

وبفضل الجميع لأفكارك - أنها ساعدت حقا.

نصائح أخرى

واحد طريقة بسيطة لأنها ستكون كما يلي:

class Float
  def prettify
    to_i == self ? to_i : self
  end
end

وهذا للأسباب التالية:

irb> 1.0 == 1
=> true
irb> 1 == 1.0
=> true

وبعد ذلك يمكن أن تفعله:

irb> 1.0.prettify
=> 1

irb> 1.5.prettify
=> 1.5

وA sprintf بطانة واحدة ...

sprintf("%g", 5.0)
=> "5"

sprintf("%g", 5.5)
=> "5.5"

وأنا لا أعرف الكثير عن روبي.

ولكن هذا هو عرض المشكلة. سأكون مندهشا للغاية إذا كنت تستخدم مكتبات لا تملك وسيلة لتنسيق الرقم عند تحويلها إلى سلسلة.

قد لا يكون هناك والتقاط كل خيار التنسيق الذي يفعل بالضبط ما تريد ولكن يمكن أن تقوم بإعداد الأسلوب الذي يعود صحيحا إذا تعويم هو التمثيل تعويم عدد صحيح وكاذبة خلاف ذلك. داخل روتين التنسيق التي تقوم بإنشائها (بحيث يكون لديك فقط للقيام بذلك مرة واحدة في مكان) فقط تغيير تنسيق على أساس إذا كان هذا صحيحا أو خاطئا.

يناقش هذا كيفية السيطرة على عدد من الأرقام التي تظهر بعد العلامة العشرية عندما عرض عدد.

واحترس من تعقيدات العائمة تمثيل نقطة. الرياضيات قد يقول الجواب هو 3 ولكن قد تحصل 3،000000000000000000001. أنا أقترح باستخدام الدلتا لمعرفة ما إذا كان العدد تقريبا عدد صحيح.

وعلى الرغم من أنني كنت أميل إلى الاتفاق مع آخر المذكورة أعلاه، إذا كان يجب القيام بذلك:

(float == float.floor) ? float.to_i : float

إذا كنت تستخدم القضبان يمكنك استخدام المساعد number_to_rounded مع strip_insignificant_zeros الخيار، على سبيل المثال:

ActiveSupport::NumberHelper.number_to_rounded(42.0, strip_insignificant_zeros: true)

وأو من هذا القبيل:

42.0.to_s(:rounded, strip_insignificant_zeros: true)

وهنا هو بلدي تنفيذ hacktastic فظيعة تقدم للأغراض التعليمية:

class Float
  def to_int_if_whole(precision = 2)
    ("%.#{precision}f" % self).split(/\./).last == '0' * precision and self.to_i or self
  end
end

puts 1.0.to_int_if_whole # => 1
puts 2.5.to_int_if_whole # => 2.5
puts 1.9999999999999999999923.to_int_if_whole # => 2

والسبب لاستخدام الدعوة على غرار sprintf هو أنه يتعامل مع العائمة تقريبية نقطة أكثر من ذلك بكثير موثوق من الطريقة جولة تعويم # يميل إلى.

وأنا لا أعرف الكثير عن روبي سواء.

ولكن في C ++، كنت تفعل هذا:

bool IsWholeNumber( float f )
{
    const float delta = 0.0001;
    int i = (int) f;
    return (f - (float)i) < delta;
}

وبعد ذلك كنت تنسيق الدقة الانتاج بناء على ذلك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top