هل هناك وظيفة لتقريب تعويم في لغة C أم أنني بحاجة إلى كتابة دالة خاصة بي؟

StackOverflow https://stackoverflow.com/questions/497018

  •  20-08-2019
  •  | 
  •  

سؤال

هل هناك وظيفة لتقريب تعويم في لغة C أم أنني بحاجة إلى كتابة دالة خاصة بي؟

تعويم التحويل = 45.592346543;

أرغب في تقريب القيمة الفعلية إلى منزلة عشرية واحدة، تحويل = 45.6.

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

المحلول

كما ذكر روب، ربما ترغب فقط في ذلك مطبعة تعويم إلى منزلة عشرية واحدة.في هذه الحالة، يمكنك القيام بشيء مثل ما يلي:

#include <stdio.h>
#include <stdlib.h>

int main()
{
  float conver = 45.592346543;
  printf("conver is %0.1f\n",conver);
  return 0;
}

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

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main()
{
  float conver = 45.592346543;
  printf("conver is %0.1f\n",conver);

  conver = conver*10.0f;
  conver = (conver > (floor(conver)+0.5f)) ? ceil(conver) : floor(conver);
  conver = conver/10.0f;

  //If you're using C99 or better, rather than ANSI C/C89/C90, the following will also work.
  //conver = roundf(conver*10.0f)/10.0f;

  printf("conver is now %f\n",conver);
  return 0;
}

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

نصائح أخرى

بالتأكيد، يمكنك استخدام مستدير ().إذا كنت تريد التقريب إلى رقم عشري واحد، فيمكنك القيام بشيء مثل: roundf(10 * x) / 10

#include <math.h>

double round(double x);
float roundf(float x);

لا تنس الارتباط بـ -lm.انظر أيضًا ceil() وfloor() وtrunc().

فقط لتعميم إجابة روب قليلاً، إذا كنت كذلك لا عند القيام بذلك عند الإخراج، لا يزال بإمكانك استخدام نفس الواجهة مع sprintf().

أعتقد أن هناك طريقة أخرى للقيام بذلك، رغم ذلك.يمكنك المحاولة ceil() و floor() للتقريب لأعلى ولأسفل.هناك خدعة لطيفة تتمثل في إضافة 0.5، لذا فإن أي شيء يزيد عن 0.5 يتم تقريبه للأعلى ولكن أي شيء تحته يتم تقريبه للأسفل. ceil() و floor() العمل فقط على doubleرغم ذلك.

يحرر:أيضًا، بالنسبة للعوامات، يمكنك استخدامها truncf() لاقتطاع العوامات.يجب أن تعمل نفس الحيلة +0.5 لإجراء تقريب دقيق.

هناك round() وظيفة، أيضا fround(), ، والتي سيتم تقريبها إلى أقرب عدد صحيح يتم التعبير عنه كمضاعف.ولكن هذا ليس ما تريد.

كان عندي نفس المشكلة وكتبت هذا:

#include <math.h>

   double db_round(double value, int nsig)
/* ===============
**
** Rounds double <value> to <nsig> significant figures.  Always rounds
** away from zero, so -2.6 to 1 sig fig will become -3.0.
**
** <nsig> should be in the range 1 - 15
*/

{
    double     a, b;
    long long  i;
    int        neg = 0;


    if(!value) return value;

    if(value < 0.0)
    {
        value = -value;
        neg = 1;
    }

    i = nsig - log10(value);

    if(i) a = pow(10.0, (double)i);
    else  a = 1.0;

    b = value * a;
    i = b + 0.5;
    value = i / a;

    return neg ? -value : value;
} 

ل مطبعة قيمة مدورة, @ مات ج حسنا يجيب على السؤال.

float x = 45.592346543;
printf("%0.1f\n", x);  // 45.6

كما هو الحال في معظم النقاط العائمة (FP). الثنائية قائم على، بالضبط التقريب إلى واحد عدد عشري المكان غير ممكن عندما تكون الإجابة الصحيحة رياضيا x.1, x.2, ....

لتحويل رقم FP إلى الأقرب 0.1 إنها مسألة أخرى.

تجاوز:قد تتجاوز المقاربات التي يتم فيها المقياس الأول بمقدار 10 (أو 100، 1000، وما إلى ذلك) النطاقات الكبيرة x.

float round_tenth1(float x) {
  x = x * 10.0f;
  ...
}

تقريب مزدوج:إضافة 0.5f ثم الاستخدام floorf(x*10.0f + 0.5f)/10.0 إرجاع النتيجة الخاطئة عند المبلغ المتوسط x*10.0f + 0.5f تقريب إلى عدد صحيح جديد.

// Fails to round 838860.4375 correctly, comes up with 838860.5 
// 0.4499999880790710449 fails as it rounds to 0.5
float round_tenth2(float x) {
  if (x < 0.0) {
    return ceilf(x*10.0f + 0.5f)/10.0f;
  }
  return floorf(x*10.0f + 0.5f)/10.0f;
}

يصب ل int لديه مشكلة واضحة عندما float x أكبر بكثير من INT_MAX.


استخدام roundf() والعائلة، متوفر في <math.h> هو النهج الأفضل.

float round_tenthA(float x) {
  double x10 = 10.0 * x;
  return (float) (round(x10)/10.0);
}

لتجنب استخدام double, ، ما عليك سوى اختبار ما إذا كان الرقم يحتاج إلى التقريب.

float round_tenthB(float x) {
  const float limit = 1.0/FLT_EPSILON;
  if (fabsf(x) < limit) {
    return roundf(x*10.0f)/10.0f;
  }
  return x;
}

يمكنك استخدام #Define Round (A) (int) (A+0.5) كماكرو ، لذا كلما كتبت جولة (1.6) ، تعود 2 وكلما كتبت جولة (1.3) تعود 1.

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