পূর্ণসংখ্যা মড 10 এবং পূর্ণসংখ্যার বিভাজন 10 পাওয়ার দ্রুততম উপায়?


10

যদি কোনও হার্ডওয়্যার মডিউলাস বা বিভাগের ক্রিয়াকলাপ সমর্থন করে না, সফ্টওয়্যার দ্বারা মডুলাস / বিভাগ অনুকরণ করতে আরও অনেক সিপিইউ চক্র লাগে। অপারেন্ড 10 হলে ডিভিশন এবং মডিউলাস গণনা করার কোনও দ্রুত উপায় আছে?

আমার প্রকল্পে আমার প্রায়শই পূর্ণসংখ্যার মডুলাস 10 গণনা করা দরকার In বিশেষত, আমি PIC16F এ কাজ করছি এবং একটি এলসিডিতে একটি সংখ্যা দেখানো দরকার। সমর্থন করার জন্য 4 টি সংখ্যা রয়েছে, সুতরাং মডিউলাস এবং বিভাগ ফাংশন (সফ্টওয়্যার বাস্তবায়ন) এ 4 টি কল রয়েছে। এটি, নীচের মত:

digit = number % 10;    // call to an expensive function
number /= 10;           // call to an expensive function
somehow_lit_segments();

digit = number % 10;    // call to an expensive function
number /= 10;           // call to an expensive function
somehow_lit_segments();

digit = number % 10;    // call to an expensive function
number /= 10;           // call to an expensive function
somehow_lit_segments();

digit = number % 10;    // call to an expensive function
number /= 10;           // call to an expensive function
somehow_lit_segments();

অন্যান্য ক্ষেত্রগুলিও অনুরূপ কোড ব্যবহার করে।


কয়েক ডজন কল / সেকেন্ড কেন সমস্যা? প্রকল্পটি সম্পূর্ণরূপে কার্যকরী এবং বাগ-মুক্ত না হলে আমি বিরক্ত করব না।
নিক টি টি

আমি লক্ষ্য করেছি যে আমি যদি প্রধান ব্যস্ত লুপটিতে ক্রমাগত কিছু নম্বর প্রদর্শন করি তবে বোতামটির প্রতিক্রিয়া ধীর হয়ে যায়। অর্থাৎ, একটি বোতাম টিপে গেছে তা সনাক্ত করতে, আমাকে সেই বোতামটি আরও দীর্ঘ চাপতে হবে। সিস্টেম ক্লকটি 32768 হার্জ চলমান অবস্থায় এটি ঘটে।
ডোনোটালো

আপনি কি বাধা ব্যবহার করছেন? আপনি কেন 32kHz xtal ব্যবহার করছেন; আপনি দ্রুত অপারেট করলে এবং অলস অবস্থায় ঘুমাতে গেলে সাধারণত আপনি কম পাওয়ার পারফরম্যান্স পেতে পারেন।
নিক টি টি

আমি বাধা ব্যবহার করছি। তবে কেবল ডিসপ্লে আপডেট করার জন্য এটি উচ্চ গতির দোলনে স্যুইচ করার মতো নয়। ক্ষমতা প্রজ্ঞাময়। আমার প্রকল্পের জন্য এটি তার জীবনের প্রায় 90% সময়ের মধ্যে কম গতির ঘড়িটি চালাতে হবে।
ডোনাটোলো

2
সাধারণ নোট হিসাবে, বই হ্যাকার কল্লোল হেনরি এস ওয়ারেন দ্বারা, জুনিয়র হয় চালাক বিট-twiddling কপট জন্য উৎস। আমি বিভাগ প্রস্তাবনাগুলির সন্ধান করলাম, এবং এর 10 এর বিভাজনের জন্য এমন কিছু নেই যা নীচের উত্তরগুলির চেয়ে সেরা।
RBerteig

উত্তর:


11

বিসিডির অ্যালগরিদমের কাছে বাইনারি হেরস আমি এখানে পাওয়া একটিটির ভিত্তিতে বেশ কয়েক বছর আগে ব্যবহার করেছি । আমি একটি বহিরাগত বিসিডি থেকে 7 সেগ ডিসপ্লে ড্রাইভার ব্যবহার করছিলাম যাতে ফলাফলটি সঠিক পোর্টগুলিতে সরাসরি আউটপুট জন্য প্যাক করা বিসিডি হিসাবে লেখা যায়।

এটি মোটামুটি দ্রুত যদি আপনার পিআইসিতে একটি হার্ডওয়ার গুণক থাকে তবে আমি একটি পিক 18 এফ 97 জ 60 ব্যবহার করছিলাম। আপনার পিআইসিতে যদি হার্ডওয়্যার গুণক না থাকে তবে গুণনের জন্য শিফট + অ্যাড ব্যবহার করার বিষয়টি বিবেচনা করুন।

এটি একটি স্বাক্ষরবিহীন 16 বিট ইনট নেয় এবং 5 অঙ্ক সহ প্যাকড বিসিডি দেয়, এটি সংশোধন করতে এবং 4 সংখ্যার জন্য দ্রুত তৈরি করা যেতে পারে। এটি শিফট + সংযোজনগুলি 10 দ্বারা আনুমানিক বিভাগে ব্যবহার করে তবে সীমিত ইনপুট পরিসীমা দেওয়া হলে এটি এই ব্যবহারের জন্য সঠিক। আপনি কীভাবে ফলাফলটি ব্যবহার করছেন তা সন্ধান করতে আপনি ভিন্নভাবে ফলাফলটি প্যাক করতে চাইতে পারেন।

void intToPackedBCD( uint16_t n, uint8_t *digits ) {

    uint8_t d4, d3, d2, d1, d0, q;  //d4 MSD, d0 LSD

    d1 = (n>>4)  & 0xF;
    d2 = (n>>8)  & 0xF;
    d3 = (n>>12) & 0xF;

    d0 = 6*(d3 + d2 + d1) + (n & 0xF);
    q = (d0 * 0xCD) >> 11;
    d0 = d0 - 10*q;

    d1 = q + 9*d3 + 5*d2 + d1;
    q = (d1 * 0xCD) >> 11;
    d1 = d1 - 10*q;

    d2 = q + 2*d2;
    q = (d2 * 0x1A) >> 8;
    d2 = d2 - 10*q;

    d3 = q + 4*d3;
    d4 = (d3 * 0x1A) >> 8;
    d3 = d3 - 10*d4;

    digits[0] = (d4<<4) | (d3);
    digits[1] = (d2<<4) | (d1);
    digits[2] = (d0<<4);
}

দুর্দান্ত লিঙ্ক, ধন্যবাদ! এটি কেবল গতি অনুকূল করে না, কোডের আকারও হ্রাস করে। আমি আপনার লিঙ্ক থেকে "12 বিট বাইনারি থেকে 4 এএসসিআইআই দশমিক সংখ্যা" প্রয়োগ করেছি কারণ এতে কোনও গুণ জড়িত না।
ডোনোটালো 18

8

স্বাক্ষরবিহীন পূর্ণসংখ্যা, বিভাগ এবং গুণকে বিট শিফট থেকে গঠন করা যেতে পারে। এবং (পূর্ণসংখ্যা) বিভাগ এবং গুণ থেকে, মডিউলগুলি প্রাপ্ত করা যায়।

10 দ্বারা গুণতে:

y = (x << 3) + (x << 1);

10 দ্বারা ভাগ করা আরও কঠিন difficult আমি বিভিন্ন বিভাগ অ্যালগরিদম জানি। যদি আমি সঠিকভাবে স্মরণ করি, তবে বিট শিফট এবং বিয়োগফল ব্যবহার করে 10 দিয়ে বিভক্ত করার একটি উপায় আছে তবে আমি সঠিক পদ্ধতিটি মনে করতে পারি না। যদি এটি সত্য না হয়, তবে এটি হল একটি বিভাজন অ্যালগরিদম যা <130 টি চক্র পরিচালনা করে । আপনি কী মাইক্রো ব্যবহার করছেন তা আমি নিশ্চিত নই, তবে আপনি এটি কোনওভাবে ব্যবহার করতে পারেন, এমনকি আপনার এটি পোর্ট করতে হলেও।

সম্পাদনা: স্ট্যাক ওভারফ্লোতে কেউ বলেছেন , আপনি যদি কিছুটা ত্রুটি সহ্য করতে পারেন এবং একটি বড় অস্থায়ী রেজিস্ট্রেশন করতে পারেন তবে এটি কাজ করবে:

temp = (ms * 205) >> 11;  // 205/2048 is nearly the same as /10

আপনার বিভাজন এবং গুণ রয়েছে বলে ধরে নেওয়া, মডুলো সহজ:

mod = x - ((x / z) * z)

6

ডাবল ড্যাবল অ্যালগরিদম ব্যবহার করে আপনি কোনও বিভাগ ছাড়াই বাইনারি থেকে প্যাক বিসিডিতে রূপান্তর করতে পারেন । এটি কেবল শিফট এবং 3 যুক্ত করে

উদাহরণস্বরূপ 243 10 = 11110011 2 বাইনারি রূপান্তর করুন

0000 0000 0000   11110011   Initialization
0000 0000 0001   11100110   Shift
0000 0000 0011   11001100   Shift
0000 0000 0111   10011000   Shift
0000 0000 1010   10011000   Add 3 to ONES, since it was 7
0000 0001 0101   00110000   Shift
0000 0001 1000   00110000   Add 3 to ONES, since it was 5
0000 0011 0000   01100000   Shift
0000 0110 0000   11000000   Shift
0000 1001 0000   11000000   Add 3 to TENS, since it was 6
0001 0010 0001   10000000   Shift
0010 0100 0011   00000000   Shift
   2    4    3
       BCD

যখন কোনও হার্ডওয়্যার বিভাজন উপলব্ধ নেই তখন এই অ্যালগরিদমটি খুব কার্যকর। কেবলমাত্র 1 এর বেশি বাম শিফট ব্যবহার করা হয়, তাই ব্যারেল শিফটার উপলব্ধ না থাকলেও এটি দ্রুত


4

আপনার প্রয়োজনীয় সংখ্যার উপর নির্ভর করে আপনি ব্রুট ফোর্স পদ্ধতি ব্যবহার করতে সক্ষম হতে পারেন ( d- ইনপুট নম্বর, t- আউটপুট ASCII স্ট্রিং):

t--;
if (d >= 1000) t++; *t = '0'; while (d >= 1000) { d -= 1000; *t += 1; }
if (d >= 100) t++; *t = '0'; while (d >= 100) { d -= 100; *t += 1;}
if (d >= 10) t++; *t = '0'; while (d >= 10) { d -= 10; *t += 1;}
t++; *t = '0' + d;

গুণনের দ্বারা বা একটি অনুসন্ধান সারণী দ্বারা প্রাপ্ত দশটির শক্তি সহ আপনি একাধিক আইএফসকে একটি লুপেও পরিবর্তন করতে পারেন।


2

এই অ্যাপ্লিকেশন নোটটিতে বিসিডি গাণিতিকগুলির জন্য বাইনারি থেকে বিসিডিতে রূপান্তরকরণ এবং এর বিপরীতে আলগোরিদিমগুলি বর্ণনা করা হয়েছে। অ্যাপনোটটি এটমেল, যা এভিআর, তবে বর্ণিত অ্যালগরিদমগুলি প্রসেসর-স্বতন্ত্র।


1

আমার একটি ভাল উত্তর নেই, তবে বিভাগ এবং মডুলো অপ্টিমাইজেশনের ঠিক একই বিষয়ে আমাদের বোন সাইটের স্ট্যাক ওভারফ্লোতে একটি দুর্দান্ত আলোচনা রয়েছে।

আপনার কি দেখার সারণি বাস্তবায়নের জন্য পর্যাপ্ত মেমরি রয়েছে?

হ্যাকারস ডিলাইটের অনুকূল বিভাগের অ্যালগরিদমে একটি কাগজ রয়েছে ।


না, পর্যাপ্ত স্মৃতি নেই। আমি যোগ, বিয়োগ এবং বিট শিফট ব্যবহার করে এটি করতে চাই।
ডোনাটোলো

1

আপনি কি সেই মানটি সর্বদা বিসিডি হিসাবে ধরে রাখার (সাধারণ বিশেষ "বিসিডি ইনক্রিমেন্ট" এবং "বিসিডি অ্যাড" সাবরুটাইনগুলি ব্যবহার করে) পরিবর্তে সেই মানটি বাইনারি আকারে ধরে রাখার পরিবর্তে এবং প্রয়োজন অনুসারে বিসিডিতে রূপান্তরিত করার পরিবর্তে (রূপান্তরকে আরও বুঝতে অসুবিধে করে বোঝার ফলে) বাইনারি থেকে বিসিডি "সাব্রোটিন)?

এক সময়, সমস্ত কম্পিউটার দশমিক সংখ্যা (দশ-অবস্থানের গিয়ার্স, পাঁচ-এর বাইরে পাঁচটি কোড ভ্যাকুয়াম টিউব, বিসিডি ইত্যাদি) হিসাবে সমস্ত ডেটা সংরক্ষণ করে এবং সেই উত্তরাধিকার আজও স্থায়ী। (দেখুন কেন রিয়েল-টাইম ক্লক চিপস বিসিডি ব্যবহার করে )।


এলসিডিতে প্রদর্শিত নম্বরটি একটি পরিবর্তনশীল, -1999 থেকে 1999 সাল পর্যন্ত এটি একটি তাপমাত্রা নির্দেশ করে এবং বাইনারি বিন্যাসে গণনা করা হয়।
ডোনাটোলো

1

PICList আমাদের PIC প্রসেসর প্রোগ্রামিং মানুষের জন্য একটি বিস্ময়কর সম্পদ।

বিসিডি রূপান্তর

আপনি কি অফ-দ্য-শেল্ফ-ব্যবহার-পরীক্ষা-পরীক্ষা-বাইনারি-টু-বিসিডি সাবউরটিনটি বিশেষত PIC16F- এর জন্য অনুকূলিত করেছেন?

বিশেষত, পিআইসিএলিস্টে থাকা লোকেরা একটি পিক 16 এফ-তে বাইনারি-থেকে-বিসিডি রূপান্তরকে অনুকূলকরণ করতে অনেক সময় ব্যয় করেছে। এই রুটিনগুলি (প্রতিটি একটি নির্দিষ্ট আকারের জন্য হ্যান্ড-অপ্টিমাইজড) সংক্ষিপ্তসারিত হয় "পিআইসি মাইক্রোকন্টোলার রেডিক্স রূপান্তর গণিত পদ্ধতিসমূহ" http://www.piclist.com/techref/microchip/math/radix/index.htm

পূর্ণসংখ্যা বিভাগ এবং মোড

পিআইসি 16 এফের মতো সিপিইউতে একটি ধ্রুবক দ্বারা বিভাজনের জন্য বিশেষায়িত একটি সাবরুটিন প্রায়শই সাধারণ-উদ্দেশ্য "ভেরিয়েবল বি দ্বারা বিভাজক এ" বিভাজনের চেয়ে অনেক দ্রুত হয়। আপনি "ধ্রুবক গুণ / বিভাগের জন্য কোড উত্পন্নকরণ" http://www.piclist.com/techref/piclist/codegen/constdivmul.htm বা আপনার চেক আউট পরীক্ষা করতে পারেন (এই ক্ষেত্রে "0.1") আপনার ধ্রুবকটি রাখতে পারেন http://www.piclist.com/techref/microchip/math/basic.htm এর কাছে ক্যান রুটিন ।


1

একটি 8x8 হার্ডওয়্যার গুণিত হিসাবে, কেউ একটি নিয়মিত ব্যবহার করে একটি সালিস আকারের সংখ্যার একটি ডিভোড -10 গণনা করতে পারেন যা প্রক্রিয়াটির মাধ্যমে 0-2559 রেঞ্জের মধ্যে 12-বিট সংখ্যার জন্য এটির গুণ করে:

  1. অরিজিনাল: আসল
  2. মূল সংখ্যাটি দুটি দ্বারা ভাগ করুন এবং এটি টেম্পএইচ: টেম্পল এ সঞ্চয় করুন
  3. টেম্পএল * 51 এর এমএসবি যুক্ত করুন টেম্পএইচ * 51 এর এলএসবিতে। এটি আনুমানিক ভাগফল
  4. মানটির এমএসবি ত্যাগ করে আনুমানিক ভাগফলকে 10 দ্বারা গুণ করুন।
  5. মূল নম্বরটির এলএসবি থেকে ফলাফলের এলএসবি বিয়োগ করুন।
  6. যদি মানটি 10 ​​বা ততোধিক হয় (সর্বাধিক 19 হবে), 10 কে বিয়োগ করুন এবং আনুমানিক ভাগফলে 1 যুক্ত করুন

আমি একটি ডিভোড রুটিন লেখার পরামর্শ দেব যা নম্বরটির এমএসবি ডাব্লুতে থাকবে, এবং এলএসবি এফএসআর দ্বারা নির্দেশিত; রুটিনটি পোস্ট-হ্রাসের সাথে এফএসআরতে ভাগ করে রাখা উচিত এবং বাকীটি ডব্লিউ-তে রেখে দেওয়া উচিত a২-বিট দীর্ঘ দীর্ঘকে 10 দ্বারা বিভক্ত করতে, এরপরে এমন কিছু ব্যবহার করা উচিত:

  মুভি 0
  lfsr 0, _ সংখ্যা + 3; এমএসবির দিকে নির্দেশ করুন
  _divmod10_step কল করুন
  _divmod10_step কল করুন
  _divmod10_step কল করুন
  _divmod10_step কল করুন

একটি ডিভোড -6 ধাপটি একই রকম হবে, 51 এবং 10 এর পরিবর্তে 85 এবং 6 এর ধ্রুবক ব্যবহার ব্যতীত, উভয় ক্ষেত্রেই আমি প্রত্যাশা করব যে divmod10_step 20 চক্র (কল / রিটার্নের জন্য আরও চার) হবে তাই একটি সংক্ষিপ্ত ডিভোড 10 হবে প্রায় 50 টি চক্র এবং একটি লম্বা ডিভোড 10 প্রায় 100 হবে (যদি কোনও বিশেষ ক্ষেত্রে প্রথম পদক্ষেপ নেওয়া হয় তবে কয়েকটি চক্র সংরক্ষণ করতে পারে)।


1

এটি দ্রুততম নাও হতে পারে তবে এটি একটি সহজ উপায়।

 a = 65535;

    l = 0;
    m = 0;
    n = 0;
    o = 0;
    p = 0;

    while (a >= 10000)
    {   a -= 10000;
        l += 1;
    }
     while (a >= 1000)
    {   a -= 1000;
        m += 1;
    }
     while (a >= 100)
    {   a -= 100;
        n += 1;
    }
     while (a >= 10)
    {   a -= 10;
        o += 1;
    }
     while (a > 0)
    {   a -= 1;
        p += 1;
    }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.