سؤال

أحاول إنشاء خوارزمية تؤدي إلى صحة أن القيمة المزدوجة هي عضو في نطاق محدد بقيم Min و Max و Step. المشكلة هي التحقق من أن القيمة تطيع قاعدة الخطوة. بالنسبة للأعداد الصحيحة ، يمكن القيام بذلك بسهولة:

 boolean validate(int value, int min, int step, int max){
      return value >= min &&
             value <= max &&

             //Step should be relative to the min value not to 0.
             (value-min) % step == 0;  
 }

هذا ولكن هذا لا يعمل لقيم مزدوجة. أعلم أن هذا جزئيًا على الأقل هو لأسباب دقيقة وحاولت اختراق حل عن طريق ضرب جميع القيم برقم مرتفع للغاية وتحويلها إلى Longs. هذا لم ينجح من أجل كل القيم ، ولم يسمح بانحراف صغير من 0 عند التحقق من الباقي. هل واجه أي شخص هذه المشكلة وتوصل إلى حل جيد؟ فيما يلي مثال واختبار يضم طريقة التحقق من عدم العمل.

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

أنا ممتن لأي مؤشرات ...

التحيات / هنريك

public class ValidationExample {

public static void main(String[] args) {
    /*Range: 
        min  -10.5
        step .3
        max  -5
    */

    //Invalid values
    double[] a = {-11,-10.6,-10.4,-10.3,-10.1,-10.0,-9.8,-9.7,
            -9.5,-9.4,-9.2,-9.1,-8.9,-8.8,-8.6,-8.5,-8.3,
            -8.2,-8,-7.9,-7.7,-7.6,-7.4,-7.3,-7.1,-7.0,
            -6.8,-6.7,-6.5,-6.4,-6.2,-6.1,-5.9,-5.8,-5.6,
            -5.5,-5.3,-5.2,-5.0,-4.9,-4.8,2};

    //Valid values
    double[] b = {-10.5,-10.2,-9.9,-9.6,-9.3,-9.0,-8.7,-8.4,
            -8.1,-7.8,-7.5,-7.2,-6.9,-6.6,-6.3,-6.0,-5.7,
            -5.4,-5.1};

    for(double d : a){
        if(validate(d,-10.5,.3,-5))
            System.err.println(d + " was considered valid.");
    }

    for(double d : b){
        if(!validate(d, -10.5,.3,-5))
            System.err.println(d + " was considered invalid");
    }

    /*
     * Range
     *  min  2
     *  step .05
     *  max  3
     */

    //Invalid values
    double[] c = {1.09,2.055,2.06,2.14,2.16,2.56,2.97,3.05};

    //Valid values
    double[] e = {2.0,2.05,2.1,2.15,2.2,2.25,2.5,2.75,2.95,3.0};

    for(double d : c){
        if(validate(d,2,.05,3))
            System.err.println(d + " was considered valid.");
    }

    for(double d : e){
        if(!validate(d,2,.05,3))
            System.err.println(d + " was considered invalid.");
    }

}

private static boolean 
    validate(double value, double min, double step, double max){
    return value >= min && 
           value <= max &&
           (value - min) % step == 0;
}

}

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

المحلول

لو value يتبع قاعدة الخطوة ، ثم (value - min)/step يجب أن يكون عدد صحيح. لذلك يمكنك التحقق من مدى قربه من أقرب عدد صحيح ، وتحديد ما إذا كانت المسافة مهمة أم لا.

double ratio = (value-min)/step;
double distance = Math.Abs(ratio - Math.Round(ratio,0));
return distance < treshold;

نصائح أخرى

بصرف النظر عن كونك غير أنيق للغاية ، وربما بطيئة ، إضافة step بشكل مستمر للاقتراب من العدد الذي يتم فحصه سيؤدي إلى حسابات أقل دقة لأن أخطاء النقطة العائمة تميل إلى التراكم.

لا أعرف جافا جيدًا ، لكن الخوارزمية للقيام بذلك هي أن تأخذ النسبة: (value-min)/step, ، حوله إلى أقرب عدد صحيح n, ثم احسب v = min+step*n. لو v و value "قريبة بما فيه الكفاية" ، ثم يمكنك وضع علامة value كما ساري المفعول.

لاختبار قيم "إغلاق بما فيه الكفاية" ، يجب على المرء استخدام تسامح قريب ومطلق. على سبيل المثال ، الحزمة FCMP ينفذ خوارزمية جيدة إلى حد ما لمقارنة قيم الفاصلة العائمة.

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