NET ফ্রেমওয়ার্কে ম্যাথ.প্যাও () কীভাবে প্রয়োগ করা হয়?


432

আমি একটি (বলুন a = 2এবং b = 50) গণনা করার জন্য একটি দক্ষ পদ্ধতির সন্ধান করছিলাম । জিনিসগুলি শুরু করার জন্য, আমি Math.Pow()ফাংশনটির বাস্তবায়নটি একবার দেখে নেওয়ার সিদ্ধান্ত নিয়েছি । কিন্তু নেট নেট রিফ্লেক্টরে আমি যা পেয়েছি তা হ'ল:

[MethodImpl(MethodImplOptions.InternalCall), SecuritySafeCritical]
public static extern double Pow(double x, double y);

আমি যখন Math.Pow()ফাংশন বলি তখন কী কী সংস্থানগুলি আমি দেখতে পাচ্ছি ভিতরে কী চলছে ?


15
ঠিক একটি এফওয়াইআই হিসাবে, আপনি যদি InternalCallকোনও externসংশোধক ( পুরোপুরি বিরোধী বলে মনে করেন) দিয়ে পুরো সম্পর্কে বিভ্রান্ত হন তবে দয়া করে আমি এই প্রশ্নটি সম্পর্কে পোস্ট করা প্রশ্নটি (এবং ফলস্বরূপ উত্তরগুলি) দেখুন
ক্রেগটিপি

6
কোনও 2^xঅপারেশনের জন্য যদি xপূর্ণসংখ্যা হয় তবে ফলাফলটি একটি শিফট অপারেশন। সুতরাং আপনি একটি ম্যান্টিসার 2এবং একটি উদ্দীপক ব্যবহার করে ফলাফলটি তৈরি করতে পারেন x
ja72

@ সুরজজাইন আপনার মন্তব্যটি আসলে একটি প্রশ্ন যা আপনার আলাদাভাবে পোস্ট করা দরকার।
j72 72

@ সুরজজাইন আমি আপনার সাথে একমত আমি মডারেটর নই তাই এখানে বেশি কিছু করতে পারছি না। হয়তো ডাউনটা
প্রশ্নটি

উত্তর:


854

MethodImplOptions.InternalCall

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

কোডটি দেখার জন্য সিএলআর এর উত্স কোডের প্রয়োজন। আপনি এটি এসএসসিএলআই 20 বিতরণ থেকে পেতে পারেন । এটি .NET 2.0 টাইম ফ্রেমের চারপাশে লেখা হয়েছিল, আমি নিম্ন-স্তরের বাস্তবায়ন খুঁজে পেয়েছি, Math.Pow()সিএলআরের পরবর্তী সংস্করণগুলির জন্য এখনও বেশিরভাগ ক্ষেত্রে সঠিক হতে চাই ।

চেহারা টেবিলটি clr / src / vm / ecall.cpp এ অবস্থিত। বিভাগটি Math.Pow()দেখতে এটির মতো প্রাসঙ্গিক :

FCFuncStart(gMathFuncs)
    FCIntrinsic("Sin", COMDouble::Sin, CORINFO_INTRINSIC_Sin)
    FCIntrinsic("Cos", COMDouble::Cos, CORINFO_INTRINSIC_Cos)
    FCIntrinsic("Sqrt", COMDouble::Sqrt, CORINFO_INTRINSIC_Sqrt)
    FCIntrinsic("Round", COMDouble::Round, CORINFO_INTRINSIC_Round)
    FCIntrinsicSig("Abs", &gsig_SM_Flt_RetFlt, COMDouble::AbsFlt, CORINFO_INTRINSIC_Abs)
    FCIntrinsicSig("Abs", &gsig_SM_Dbl_RetDbl, COMDouble::AbsDbl, CORINFO_INTRINSIC_Abs)
    FCFuncElement("Exp", COMDouble::Exp)
    FCFuncElement("Pow", COMDouble::Pow)
    // etc..
FCFuncEnd()

"COMDouble" অনুসন্ধান করা আপনাকে clr / src / classlibnative / float / comfloat.cpp এ নিয়ে যায়। আমি আপনাকে কোডটি ছাড়ব, কেবল নিজের জন্য দেখুন। এটি মূলত কোণার কেসগুলি পরীক্ষা করে, তারপরে সিআরটি'র সংস্করণকে কল করে pow()

কেবলমাত্র অন্য বাস্তবায়ন বিশদটি যা আকর্ষণীয় তা হ'ল টেবিলে FCIntrinsic ম্যাক্রো। এটি একটি ইঙ্গিত যা ঘিটারটি অভ্যন্তরীণ হিসাবে ফাংশনটি প্রয়োগ করতে পারে। অন্য কথায়, ফ্লোটিং পয়েন্ট মেশিন কোড নির্দেশের সাথে ফাংশন কলটির বিকল্প দিন। যার ক্ষেত্রে এটি নয় Pow(), এর জন্য কোনও এফপিইউ নির্দেশনা নেই। তবে অবশ্যই অন্যান্য সাধারণ অপারেশনগুলির জন্য। উল্লেখযোগ্য যে, এই C # ফ্লোটিং পয়েন্ট গণিত যথেষ্ট দ্রুত সি একই কোড চেয়ে করা যায় ++ পরীক্ষা এই উত্তর কারণে জন্য।

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

public static double FasterPow(double x, double y) {
    return Math.Exp(y * Math.Log(x));
}

তবে সত্যিকারের বিকল্প নয় কারণ এটি 3 ভাসমান পয়েন্ট অপারেশনগুলি থেকে ত্রুটি সংগ্রহ করে এবং পাওয়ার () এর যে অদ্ভুত ডোমেন সমস্যা রয়েছে তা মোকাবেলা করে না। 0 ^ 0 এবং -অনফিনিটি যেকোন শক্তি বাড়িয়েছে।


437
দুর্দান্ত উত্তর, স্ট্যাকওভারফ্লো'র পরিবর্তে 'আপনি কেন এটি জানতে চান?' যে সব প্রায়ই ঘটে।
টম ডাব্লু

16
@ ব্লু - আমি জানি না, ইন্টেল ইঞ্জিনিয়ারদের নিয়ে মজা করা কম। আমার উচ্চ বিদ্যালয়ের বইতে নেতিবাচক ইন্টিগ্রালটির শক্তিতে কিছু বাড়ানোর সমস্যা রয়েছে have পাও (এক্স, -২) পুরোপুরি গণনাযোগ্য, পাও (এক্স, -২.১) অপরিজ্ঞাত। ডোমেন সমস্যাগুলি মোকাবিলা করার জন্য দুশ্চরিত্রা।
হ্যানস প্যাস্যান্ট

12
@ ব্লুরাজা-ড্যানিফ্লুঘুফুট: ভাসমান-পয়েন্ট অপারেশনগুলি যথাযথভাবে গোলাকৃত মানের যতটা সম্ভব তার কাছাকাছি রয়েছে তা নিশ্চিত করার জন্য প্রচুর প্রচেষ্টা ব্যয় করা হয়েছে। powক্ষুদ্রতর ক্রিয়াকলাপ হওয়ায় সঠিকভাবে প্রয়োগ করা কুখ্যাত, ( সারণী প্রস্তুতকারকের দ্বিধা দেখুন )। এটি একটি অবিচ্ছেদ্য শক্তি দিয়ে অনেক সহজ।
porges

9
@ હંস প্যাস্যান্ট: কেন পাও (এক্স, -২.১) অপরিজ্ঞাত হবে? গাণিতিকভাবে পাগুলি সমস্ত x এবং y এর জন্য সর্বত্র নির্ধারিত। Negativeণাত্মক x এবং অ-পূর্ণসংখ্য y এর জন্য আপনি জটিল সংখ্যা পেতে চান না।
জুলাই

8
@ জুলস পাউ (0, 0) সংজ্ঞায়িত হয়নি।
এমবসস

110

হান্স পাসেন্টের উত্তর দুর্দান্ত, তবে আমি যুক্ত করতে চাই যে যদি bকোনও পূর্ণসংখ্যা হয় তবে a^bবাইনারি পচনের সাথে খুব দক্ষতার সাথে গণনা করা যায়। হেনরি ওয়ারেনের হ্যাকার ডেলাইটের একটি পরিবর্তিত সংস্করণ এখানে :

public static int iexp(int a, uint b) {
    int y = 1;

    while(true) {
        if ((b & 1) != 0) y = a*y;
        b = b >> 1;
        if (b == 0) return y;
        a *= a;
    }    
}

তিনি নোট করেছেন যে এই অপারেশনটি সর্বোত্তম (গাণিতিক বা যৌক্তিক অপারেশনগুলির ন্যূনতম সংখ্যাটি করে) সমস্ত বি <15. এছাড়াও a^bবিস্তৃত ব্যতীত অন্য কোনও বিয়ের জন্য গুণমানগুলির অনুকূল সিকোয়েন্স সন্ধান করার সাধারণ সমস্যার কোনও সমাধান নেই is অনুসন্ধান করুন। এটি একটি এনপি-হার্ড সমস্যা। সুতরাং মূলত এর অর্থ হ'ল বাইনারি পচে যাওয়া যত ভাল হয় তত ভাল।


11
এই অ্যালগরিদম ( বর্গাকার এবং গুণ ) এছাড়াও যদি aভাসমান পয়েন্ট সংখ্যা হয় তবে প্রযোজ্য ।
কোডসইনচাউস

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

পাঠ্যটিতে aএকটি পূর্ণসংখ্যা হিসাবে উল্লেখ করা হয়নি , তবে কোডটি রয়েছে। এর ফলস্বরূপ, আমি পাঠ্যের "অত্যন্ত দক্ষ" গণনার ফলাফলের যথার্থতা সম্পর্কে অবাক হয়েছি ।
অ্যান্ড্রু মর্টন

69

যদি অবাধে উপলব্ধ সি সংস্করণটিরpow কোনও ইঙ্গিত থাকে তবে এটি এমন কোনও কিছুর মতো দেখায় না যা আপনি আশা করেন। .NET সংস্করণটি খুঁজে পেতে আপনার পক্ষে খুব বেশি সহায়ক হবে না, কারণ আপনি যে সমস্যাটি সমাধান করছেন (অর্থাত্ পূর্ণসংখ্যা সহকারে) তা বিশাল আকারের আদেশ, এবং সি # কোডের কয়েকটি লাইনে এক্সপেনসেন্টেশন সহ সমাধান করা যেতে পারে because স্কোয়ারিং অ্যালগরিদম দ্বারা


আপনার উত্তরের জন্য ধন্যবাদ. প্রথম লিঙ্কটি আমাকে অবাক করেছিল কারণ আমি পাও () ফাংশনটির এত বড় প্রযুক্তিগত বাস্তবায়ন আশা করছিলাম না। যদিও হান্স প্যাস্যান্ট উত্তরটি নিশ্চিত করে যে এটি। নেট ওয়ার্ল্ডেও একই রকম। আমি মনে করি স্কোয়ারিং অ্যালগরিদম লিঙ্কে তালিকাবদ্ধ কয়েকটি কৌশল ব্যবহার করে আমি সমস্যার সমাধান করতে পারি। আবার ধন্যবাদ.
পবন মিশ্র

2
আমি বিশ্বাস করি না যে এই কোডটি দক্ষ। 30 স্থানীয় ভেরিয়েবলগুলি কেবলমাত্র সমস্ত রেজিস্টারগুলিকে টুকরো টুকরো করে। আমি কেবল অনুমান করি এটির এআরএম সংস্করণ তবে x86 এ 30 পদ্ধতিতে স্থানীয় ভেরিয়েবলগুলি দুর্দান্ত।
অ্যালেক্স ঝুকভস্কি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.