سؤال

لدي تعويم بدائي وأحتاج كدليل بدائي. ما عليك سوى إلقاء تعويم مزدوج يمنحني دقة إضافية غريبة. علي سبيل المثال:

float temp = 14009.35F;
System.out.println(Float.toString(temp)); // Prints 14009.35
System.out.println(Double.toString((double)temp)); // Prints 14009.349609375

ومع ذلك، إذا بدلا من الصب، أقوم بإخراج الطفو كسلسلة، وتحليل السلسلة مزدوجة، أحصل على ما أريد:

System.out.println(Double.toString(Double.parseDouble(Float.toString(temp))));
// Prints 14009.35

هل هناك طريقة أفضل من الذهاب إلى السلسلة والظهر؟

هل كانت مفيدة؟

المحلول

ليس ذلك فعلا الحصول على دقة إضافية - إنه أن تعويم لا يمثل الرقم بدقة الرقم الذي كنت تهدف إليه في الأصل. مزدوج يكون يمثل الطفو الأصلي بدقة؛ toString يظهر البيانات "الإضافية" التي كانت موجودة بالفعل.

على سبيل المثال (وهذه الأرقام ليست صحيحة، أنا فقط جعل الأمور) لنفترض أن لديك:

float f = 0.1F;
double d = f;

ثم قيمة f قد يكون بالضبط 0.100000234523. d سيكون لها نفس القيمة بالضبط، ولكن عند تحويلها إلى سلسلة، ستعمل "الثقة" أنها دقيقة بدقة أعلى، لذلك لن يتم جولة في وقت مبكر، وسترى "الأرقام الإضافية" التي كانت بالفعل هناك، ولكن مخفي منك.

عند التنقل إلى سلسلة وظهر، يمكنك إنهاء قيمة مزدوجة أقرب إلى قيمة السلسلة أكثر من التعويم الأصلي كانت - ولكن هذا جيد فقط إذا تعتقد حقا أن قيمة السلسلة هي ما تريده حقا.

هل أنت متأكد من أن تعويم / مزدوج هي الأنواع المناسبة لاستخدامها هنا بدلا من BigDecimalب إذا كنت تحاول استخدام الأرقام التي لها قيم عشرية دقيقة (مثل الأموال)، ثم BigDecimal هو نوع المنظمة البحرية الدولية أكثر ملاءمة.

نصائح أخرى

أجد التحويل إلى التمثيل الثنائي أسهل لفهم هذه المشكلة.

float f = 0.27f;
double d2 = (double) f;
double d3 = 0.27d;

System.out.println(Integer.toBinaryString(Float.floatToRawIntBits(f)));
System.out.println(Long.toBinaryString(Double.doubleToRawLongBits(d2)));
System.out.println(Long.toBinaryString(Double.doubleToRawLongBits(d3)));

يمكنك أن ترى تعويم توسيعها إلى المزدوج عن طريق إضافة 0s إلى النهاية، ولكن تمثيل مزدوج 0.27 هو "أكثر دقة"، وبالتالي المشكلة.

   111110100010100011110101110001
11111111010001010001111010111000100000000000000000000000000000
11111111010001010001111010111000010100011110101110000101001000

هذا بسبب عقد Float.toString(float), الذي يقول جزئيا:

كم عدد الأرقام التي يجب طباعةها للجزء الكسري [...]؟ يجب أن يكون هناك رقم واحد على الأقل لتمثيل الجزء الكسري، وما بعد ذلك ولكن فقط أكبر عدد ممكن، هناك حاجة إلى المزيد من الأرقام لتتميز قيمة الوسيطة بشكل فريد من القيم المجاورة للنوع تعويم. وهذا هو، لنفترض أن X هي القيمة الرياضية الدقيقة التي يمثلها التمثيل العشري الناتج عن هذه الطريقة للحجة غير الضروتية المحدودة و. ثم يجب أن تكون F قيمة تعويم الأقرب إلى x؛ أو، إذا كانت قيمان تعويما على قدم المساواة من X، يجب أن تكون F واحدة منها واحدا منهم وأقل بت كبير من أهمية F يجب أن يكون 0.

لقد واجهت هذه المشكلة اليوم ولا يمكنها استخدام Refactor to BigDeMaly، لأن المشروع ضخم حقا. ومع ذلك وجدت الحل باستخدام

Float result = new Float(5623.23)
Double doubleResult = new FloatingDecimal(result.floatValue()).doubleValue()

وهذا يعمل.

لاحظ أن استدعاء النتيجة. Reblevalue () إرجاع 5623.298046875

ولكن استدعاء doubleresult.doplevalue () إرجاع بشكل صحيح 5623.23

لكنني لست متأكدا تماما إذا كان الحل الصحيح.

إستخدم BigDecimal بدلا من float/double. وبعد هناك الكثير من الأرقام التي لا يمكن تمثيلها باعتبارها نقطة عائمة ثنائية (على سبيل المثال، 0.1). لذلك يجب عليك دائما تقريب النتيجة بدقة أو استخدام معروفة BigDecimal.

يرى http://en.wikipedia.org/wiki/floating_point. للمزيد من المعلومات.

لقد وجدت الحل التالي:

public static Double getFloatAsDouble(Float fValue) {
    return Double.valueOf(fValue.toString());
}

كما ترى يطفو و مزدوج بدلا من يطفو و مزدوج استخدم ما يلي:

public static double getFloatAsDouble(float value) {
    return Double.valueOf(Float.valueOf(value).toString()).doubleValue();
}

يطفو، بطبيعتها، غير دقيقة ولديها دائما "قضايا" التقريب ". إذا كان الدقة مهمة، فقد تفكر في إعادة تكوين تطبيقك لاستخدام عشري أو كبير.

نعم، يطفو بشكل أسرع بشكل أسرع من الكسور العشرية بسبب دعم المعالج. ومع ذلك، هل تريد بسرعة أو دقيقة؟

للحصول على معلومات يأتي هذا في إطار البند 48 - تجنب تعويم ومضاعف عند حاجة القيم الدقيقة، من إصدار Java 2nd الفعال من Joshua Bloch. هذا الكتاب هو مربى معبأة مع الأشياء الجيدة وبالتأكيد يستحق نظرة.

هل هذا فعال؟

float flt = 145.664454;

Double dbl = 0.0;
dbl += flt;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top