هل يمكنني حساب الأسرى(10 x) في وقت التحويل البرمجي في c ؟

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

  •  21-08-2019
  •  | 
  •  

سؤال

هل من الممكن حساب الأسرى(10 x) في تجميع الوقت ؟

لدي المعالج دون النقطة العائمة دعم بطيئة قسمة عدد صحيح.أحاول تنفيذ العديد من العمليات الحسابية ممكن في وقت الترجمة.أنا يمكن أن تسرع كبير في واحدة وظيفة معينة إذا كنت تمر كل x و C/pow(10,x) كما الحجج (x و C هي دائما ثابتة صحيحة ، ولكنها مختلفة الثوابت لكل مكالمة).أنا أتساءل إذا كنت يمكن أن تجعل هذه المكالمات وظيفة أقل عرضه للخطأ عن طريق إدخال الكلي الذي لا 1/pow(10,x) تلقائيا بدلا من إجبار المبرمج على حساب ذلك ؟

هناك ما قبل المعالج خدعة ؟ يمكنني أن القوة مترجم تحسين المكتبة الاتصال ؟

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

المحلول

يمكنك استخدام التدوين العلمي النقطة العائمة القيم التي هي جزء من لغة C.يبدو مثل هذا:

e = 1.602E-19   // == 1.602 * pow(10, -19)

عدد قبل E ( إن E ربما رأس المال أو صغيرة 1.602e-19) هي جزء جزء حيث مثل (توقيع) أرقام تسلسل بعد E هو الأس جزء.افتراضيا عدد من النوع double, ولكن يمكنك إرفاق النقطة العائمة لاحقة (f, F, l أو L) إذا كنت في حاجة الى float أو long double.

أنا لا أوصي إلى حزمة هذا الدلالي في الماكرو:

  1. فإنه لا عمل المتغيرات قيم النقطة العائمة, الخ.
  2. الترقيم العلمي هو أكثر قابلية للقراءة.

نصائح أخرى

وهناك عدد قليل جدا من القيم الممكنة قبل أن تجاوز عدد صحيح (أو طويلة حتى). لclarities أجل، وجعله الطاولة!

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

ودول مجلس التعاون الخليجي سوف تفعل ذلك على المستوى الأمثل عالية بما فيه الكفاية (-O1 يفعل ذلك بالنسبة لي). على سبيل المثال:

#include <math.h>

int test() {
        double x = pow(10, 4);
        return (int)x;
}

ويجمع في -O1 -m32 إلى:

        .file   "test.c"
        .text
.globl test
        .type   test, @function
test:
        pushl   %ebp
        movl    %esp, %ebp
        movl    $10000, %eax
        popl    %ebp
        ret
        .size   test, .-test
        .ident  "GCC: (Ubuntu 4.3.3-5ubuntu4) 4.3.3"
        .section        .note.GNU-stack,"",@progbits

وهذا يعمل بدون المدلى بها وكذلك - بالطبع، كنت لا تحصل على تعليمات تحميل الفاصلة العائمة في هناك، كما لينكس <لأ href = "https://en.wikipedia.org/wiki/Application_binary_interface" يختلط = "نوفولو noreferrer"> ABI يمر العائمة القيم المرجعة نقطة في سجلات FPU.

ويمكنك أن تفعل ذلك مع Boost.Preprocessor:

http://www.boost.org/ وثيقة / يبس / 1_39_0 / يبس / المعالج / وثيقة / index.html و

والرمز:

#include <boost/preprocessor/repeat.hpp>

#define _TIMES_10(z, n, data) * 10
#define POW_10(n) (1 BOOST_PP_REPEAT(n, _TIMES_10, _))

int test[4] = {POW_10(0), POW_10(1), POW_10(2), POW_10(3)};

في الواقع، من خلال استغلال المعالج C، يمكنك الحصول عليه لحساب C pow(10, x) لأي C حقيقية وx يتجزأ. نلاحظ أنه، كما أشارquinmars، C يتيح لك استخدام جملة العلمي للتعبير عن الثوابت العددية:

#define myexp 1.602E-19   // == 1.602 * pow(10, -19)

ولاستخدامها في الثوابت. مع هذا في الاعتبار، وقليلا من الذكاء، يمكننا بناء ماكرو المعالج أن يأخذ C وx والجمع بينهما إلى رمز الأسي:

#define EXP2(a, b) a ## b
#define EXP(a, b) EXP2(a ## e,b)
#define CONSTPOW(C,x) EXP(C, x)

ويمكن أن تستخدم الآن هذه كقيمة عددية ثابتة:

const int myint = CONSTPOW(3, 4); // == 30000
const double myfloat = CONSTPOW(M_PI, -2); // == 0.03141592653

في الواقع، لديك M4 الذي هو وسيلة قبل معالج أقوى من لدول مجلس التعاون الخليجي. والفرق الرئيسي بين هذين هو في دول مجلس التعاون الخليجي ليست متكررة في حين M4 هو. فإنه يجعل الأمور الممكنة مثل القيام الحساب في الوقت الترجمة (وأكثر من ذلك بكثير!). نموذج التعليمات البرمجية أدناه هو ما كنت ترغب في القيام به، أليس كذلك؟ أنا جعلت ضخمة في مصدر ملف واحد؛ ولكن عادة ما وضع تعريفات الماكرو M4 في ملفات منفصلة ولحن لي قواعد MAKEFILE. بهذه الطريقة، يتم الاحتفاظ التعليمات البرمجية من تعريفات M4 تدخلا قبيحة في شفرة المصدر C فعلت هنا.

$ cat foo.c
define(M4_POW_AUX, `ifelse($2, 1, $1, `eval($1 * M4_POW_AUX($1, decr($2)))')')dnl
define(M4_POW, `ifelse($2, 0, 1, `M4_POW_AUX($1, $2)')')dnl

#include <stdio.h>

int                     main(void)
{
  printf("2^0 = %d\n", M4_POW(2, 0));
  printf("2^1 = %d\n", M4_POW(2, 1));
  printf("2^4 = %d\n", M4_POW(2, 4));

  return 0;
}

وسطر الأوامر لتجميع هذا نموذج التعليمات البرمجية يستخدم قدرة دول مجلس التعاون الخليجي وM4 القراءة من الإدخال القياسي.

$ cat foo.c | m4 - | gcc -x c -o m4_pow -
$ ./m4_pow
2^0 = 1
2^1 = 2
2^4 = 16

وهذا الأمل مساعدة!

والإصدارات الحديثة من دول مجلس التعاون الخليجي (حوالي 4.3) وأضاف القدرة على استخدام GMP وMPFR للقيام ببعض التحسينات وقت الترجمة من خلال تقييم وظائف أكثر تعقيدا التي هي ثابتة. هذا النهج يترك التعليمات البرمجية بسيطة والمحمولة، ويثق مترجم للقيام رفع الأحمال الثقيلة.

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

إذا كنت تحتاج فقط إلى استخدام قيمة في <م> تجميع الوقت ، استخدم في العلمي مثل 1e2 لpow(10, 2)

إذا كنت ترغب في تعبئة القيم في وقت الترجمة ومن ثم استخدامها لاحقا في <م> وقت التشغيل ثم ببساطة استخدام جدول بحث لأن هناك <لأ href = "http://www.exploringbinary.com / لماذا-القوى من بين عشرة ما يصل إلى 10 إلى 22 عاما هي من الدقة كما هو والزوجي / "يختلط =" نوفولو noreferrer "> 23 فقط القوى المختلفة من 10 التي هي < م> للتمثيل بالضبط في الدقة المزدوجة

double POW10[] = {1., 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10,
1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22};

ويمكنك الحصول على صلاحيات أكبر من 10 في وقت من جدول البحث أعلاه بسرعة الحصول على النتيجة دون الحاجة إلى ضرب من قبل 10 مرارا وتكرارا، ولكن النتيجة هي مجرد قيمة وثيقة مع قوة من 10 مثل عند استخدام 10eX مع X> 22

double pow10(int x)
{
   if (x > 22)
      return POW10[22] * pow10(x - 22);
   else if (x >= 0)
      return POW10[x];
    else
        return 1/pow10(-x);
}

إذا لم يكن هناك حاجة الأسس السالبة ثم فرع النهائي يمكن إزالتها.

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

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

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

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