মডুলো অপারেটর (%) সি # তে বিভিন্ন। নেট সংস্করণের জন্য আলাদা ফলাফল দেয়


89

আমি পাসওয়ার্ডের জন্য একটি স্ট্রিং তৈরির জন্য ব্যবহারকারীর ইনপুট এনক্রিপ্ট করছি। তবে কোডের একটি লাইন ফ্রেমওয়ার্কের বিভিন্ন সংস্করণে বিভিন্ন ফলাফল দেয়। ব্যবহারকারীর দ্বারা চাপা চাবির মান সহ আংশিক কোড:

কী টিপুন: 1. পরিবর্তনশীল ascii49. কিছু গণনার পরে 'ই' এবং 'এন' এর মান:

e = 103, 
n = 143,

Math.Pow(ascii, e) % n

উপরের কোডের ফলাফল:

  • নেট। 3.5 (সি #)

    Math.Pow(ascii, e) % n
    

    দেয় 9.0

  • নেট নেট 4 (সি #)

    Math.Pow(ascii, e) % n
    

    দেয় 77.0

Math.Pow() উভয় সংস্করণে সঠিক (একই) ফলাফল দেয়।

কারণ কী এবং এর কোনও সমাধান কি?


12
অবশ্যই, প্রশ্নের উভয় উত্তরই ভুল। আপনি যে বিষয়টি যত্নবান বলে মনে করছেন না এটি হ'ল ভাল, উদ্বেগজনক।
ডেভিড হেফারনান

34
আপনাকে বেশ কয়েকটি পদক্ষেপ ফিরে যেতে হবে। "আমি পাসওয়ার্ডের জন্য একটি স্ট্রিং তৈরির জন্য ব্যবহারকারীর ইনপুটটি এনক্রিপ্ট করছি" এই অংশটি ইতিমধ্যে সন্দেহজনক। আপনি আসলে কি করতে চান? আপনি কি এনক্রিপ্ট করা বা হ্যাশ আকারে একটি পাসওয়ার্ড সংরক্ষণ করতে চান? আপনি কি এলোমেলো মান উত্পন্ন করতে এন্ট্রপি হিসাবে ব্যবহার করতে চান? আপনার সুরক্ষা লক্ষ্য কি?
CodeInChaos 14

49
যদিও এই প্রশ্নটি ভাসমান পয়েন্ট গণিতের সাথে একটি আকর্ষণীয় সমস্যা চিত্রিত করে, ওপির লক্ষ্য যদি "পাসওয়ার্ডের জন্য একটি স্ট্রিং উত্পন্ন করার জন্য ব্যবহারকারীর ইনপুট এনক্রিপ্ট করে" থাকে তবে আমি মনে করি না যে আপনার নিজের এনক্রিপশনটি ঘুরিয়ে দেওয়া একটি ভাল ধারণা, তাই আমি সুপারিশ করব না প্রকৃতপক্ষে উত্তরগুলির কোনও বাস্তবায়ন
হ্যারিসন পেইন

18
অন্যান্য ভাষাগুলি কেন %ভাসমান-পয়েন্ট সংখ্যা সহ ব্যবহার করতে নিষেধ করেছে তা দুর্দান্ত প্রদর্শন ।
বেন ভয়েগট

4
উত্তরগুলি ভাল হলেও, তাদের কেউই .NET 3.5 এবং 4 এর মধ্যে কী পরিবর্তিত হয়েছে এমন প্রশ্নের উত্তর দেয় না যা বিভিন্ন আচরণের কারণ হয়ে উঠছে।
মিসেল

উত্তর:


160

Math.Powডাবল-স্পষ্টতা ভাসমান-পয়েন্ট সংখ্যাগুলিতে কাজ করে; সুতরাং, আপনি ফলাফলের প্রথম 15-17 অঙ্কের চেয়ে বেশি আশা করবেন না :

সমস্ত ভাসমান-বিন্দুর সংখ্যাতেও সীমিত সংখ্যক উল্লেখযোগ্য সংখ্যা থাকে যা ভাসমান-পয়েন্টের মানটি একটি আসল সংখ্যার সাথে কতটা সঠিকভাবে নির্ধারণ করে তাও নির্ধারণ করে। একটি Doubleমানের 15 দশমিক সংখ্যক যথার্থতা থাকে তবে সর্বোচ্চ 17 ডিজিট অভ্যন্তরীণভাবে বজায় থাকে।

তবে মডুলো পাটিগণিতের জন্য সমস্ত অঙ্ক সঠিক হওয়া দরকার। আপনার ক্ষেত্রে, আপনি 49 কম্পিউটিং হয় 103 , যার ফলাফলের 175 ডিজিটের নিয়ে গঠিত, উভয় আপনার উত্তর মডিউল অপারেশন অর্থহীন করে।

সঠিক মানটি তৈরির জন্য, BigIntegerক্লাস দ্বারা সরবরাহ করা (। নেট 4.0 এ প্রবর্তিত) হিসাবে আপনার স্বেচ্ছাচারিতা-নির্ভুলতা পাটিগণিত ব্যবহার করা উচিত ।

int val = (int)(BigInteger.Pow(49, 103) % 143);   // gives 114

সম্পাদনা করুন : নীচের মন্তব্যে মার্ক পিটারসের নির্দেশ অনুসারে, আপনার সেই BigInteger.ModPowপদ্ধতিটি ব্যবহার করা উচিত , যা এই ধরণের অপারেশনের জন্য বিশেষভাবে উদ্দেশ্যে করা হয়েছে:

int val = (int)BigInteger.ModPow(49, 103, 143);   // gives 114

20
আসল সমস্যাটি নির্দেশ করার জন্য +1, যথা প্রশ্নের কোডটি সরল ভুল
ডেভিড হেফারনান

36
এটি লক্ষণীয় যে বিগইন্টিজার একটি ModPow () পদ্ধতি সরবরাহ করে যা এই ক্রিয়াকলাপের জন্য প্রায় 5 গুণ দ্রুত (বর্তমানে আমার দ্রুত পরীক্ষায়) সম্পাদন করে।
মার্ক পিটারস

8
সম্পাদনা সহ +1 ModPow কেবল দ্রুত নয়, এটি সংখ্যাগতভাবে স্থিতিশীল!
রায়

4
@ নির্মাতা না, উত্তরটি অর্থহীন , অবৈধ নয় ।
কোডি ধূসর

4
@ মেকারফথিংস 7: আমি নীতিগতভাবে আপনার সাথে একমত। যাইহোক, অসম্পূর্ণতা অস্থায়ী পাটিগণিতের অন্তর্নিহিত, এবং সাধারণভাবে অপারেশনগুলিতে সীমাবদ্ধতা আরোপ করার চেয়ে বিকাশকারীদের ঝুঁকি সম্পর্কে সচেতন হওয়ার প্রত্যাশা করা আরও কার্যকর বলে মনে করা হয়। যদি কেউ সত্যই "নিরাপদ" হতে চেয়েছিল, তবে ভাষার 1.0 - 0.9 - 0.1 == 0.0মূল্যায়ন করার মতো অপ্রত্যাশিত ফলাফল এড়াতে, ভাসমান-বিন্দু সমতার তুলনা নিষিদ্ধ করতে হবে false
ডগলাস

72

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

49 103 মোড 143 = হ'ল 114 (( ওল্ফ্রাম আলফার লিঙ্ক )

আপনি এই উত্তরটি গণনা করতে এই কোডটি ব্যবহার করতে পারেন:

private static int PowMod(int a, int b, int mod) {
    if (b == 0) {
        return 1;
    }
    var tmp = PowMod(a, b/2, mod);
    tmp *= tmp;
    if (b%2 != 0) {
        tmp *= a;
    }
    return tmp%mod;
}

আপনার গণনা আলাদা ফলাফল আনার কারণটি হ'ল উত্তর উত্পন্ন করার জন্য, আপনি একটি মধ্যবর্তী মান ব্যবহার করেন যা 49 103 সংখ্যার উল্লেখযোগ্য সংখ্যাগুলির বেশিরভাগ ড্রপ করে : এর 175 সংখ্যার মধ্যে প্রথম 16 টিই সঠিক!

1230824813134842807283798520430636310264067713738977819859474030746648511411697029659004340261471771152928833391663821316264359104254030819694748088798262075483562075061997649

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

* যেহেতু এই প্রশ্নটি পাসওয়ার্ড হ্যাশিংয়ের প্রসঙ্গে উচ্চ শক্তির সাথে পূর্ণসংখ্যার উত্থাপনের কথা বলে, আপনার বর্তমান পদ্ধতির সম্ভাব্যতর উন্নতির জন্য কোনও পরিবর্তন করা উচিত কিনা তা সিদ্ধান্ত নেওয়ার আগে এই উত্তর লিঙ্কটি পড়া ভাল ধারণা হতে পারে ।


20
ভাল উত্তর. আসল বিষয়টি হ'ল এটি একটি ভয়াবহ হ্যাশ ফাংশন। ওপিকে সমাধানটি পুনর্বিবেচনা করতে হবে এবং আরও উপযুক্ত অ্যালগরিদম ব্যবহার করতে হবে।
ডেভিড.পিএফএফএক্স

4
আইজাক নিউটন: আপেল যেভাবে পৃথিবীর প্রতি আকৃষ্ট হয় সেভাবেই কি চাঁদ পৃথিবীর প্রতি আকৃষ্ট হয়? @ ডেভিড.পিএফএক্স: আসল পয়েন্টটি হ'ল এটি আপেল বাছাই করার এক ভয়ংকর উপায়। নিউটনের সমাধানটি পুনর্বিবেচনা করা এবং সম্ভবত একটি সিঁড়ি সহ একজন ব্যক্তিকে ভাড়া করা দরকার।
jwg

4
@jwg ডেভিডের মন্তব্যটি এক কারণে অনেকগুলি উত্সাহ পেয়েছে। মূল প্রশ্নটি পরিষ্কার করে দিয়েছে যে অ্যালগরিদম হ্যাশ পাসওয়ার্ড ব্যবহার করা হচ্ছে, এবং এটি আসলে সেই উদ্দেশ্যে একটি ভয়াবহ অ্যালগরিদম - এটি ইতিমধ্যে প্রদর্শিত হয়েছে যেমন .NET কাঠামোর সংস্করণগুলির মধ্যে বিভক্ত হওয়ার সম্ভাবনা রয়েছে। কোনও উত্তর যা উল্লেখ করে না যে ওপিকে "অশোধন" না করে তার অ্যালগরিদমটি প্রতিস্থাপন করা দরকার যা এটি তাকে বিচ্ছিন্ন করে দিচ্ছে।
ক্রিস

@ ক্রিস মন্তব্যটির জন্য ধন্যবাদ, আমি ডেভিডের পরামর্শ অন্তর্ভুক্ত করার জন্য সম্পাদনা করেছি। আমি এটি আপনার মতো তীব্রভাবে বলি নি, কারণ ওপি-র সিস্টেমটি খেলনা বা একটি থ্রো-অ্যাওড কোড হতে পারে যা সে নিজের বিনোদনের জন্য তৈরি করে use ধন্যবাদ!
সের্গেই ক্যালিনিচেনকো

27

আপনি যা দেখছেন তা দ্বিগুণ গোলাকার ত্রুটি। Math.Powদ্বিগুণ সাথে কাজ করে এবং পার্থক্যটি নীচের মত:

.NET 2.0 এবং 3.5 => var powerResult = Math.Pow(ascii, e);রিটার্ন:

1.2308248131348429E+174

.NET 4.0 এবং 4.5 => var powerResult = Math.Pow(ascii, e);রিটার্ন:

1.2308248131348427E+174

আগে শেষ অঙ্কটি লক্ষ্য করুন Eএবং এটি ফলাফলের মধ্যে পার্থক্য সৃষ্টি করছে। এটি মডুলাস অপারেটর নয় (%)


4
পবিত্র গরুটি কি ওপিএস প্রশ্নের একমাত্র উত্তর? আমি সমস্ত মেটা "বেলা ব্লাহ সুরক্ষা ভুল প্রশ্নটি আপনার চেয়ে বেশি জানি N00b" পড়েছি এবং এখনও অবাক হয়েছি "কেন 3.5 এবং 4.0 এর মধ্যে সামঞ্জস্যপূর্ণ তাত্পর্য? চাঁদের দিকে তাকানোর সময় কখনও আপনার পায়ে একটি পাথরে আঘাত করে জিজ্ঞাসা করা হয়েছিল" কী ধরণের রক? এটি কি? "কেবল বলা যেতে পারে" আপনার আসল সমস্যাটি আপনার পায়ের দিকে তাকাচ্ছে না "বা" রাতের বেলা ঘরে তৈরি স্যান্ডেল পরে আপনি কী প্রত্যাশা করবেন? !!! "ধন্যবাদ!
মাইকেল পাউলুকোনিস

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

24

ভাসমান-পয়েন্ট যথার্থতা মেশিন থেকে অন্য মেশিনে এবং এমনকি একই মেশিনে পরিবর্তিত হতে পারে ।

যাইহোক, .NET আপনার অ্যাপ্লিকেশনগুলির জন্য একটি ভার্চুয়াল মেশিন তৈরি করে ... তবে সংস্করণ থেকে সংস্করণে পরিবর্তন রয়েছে।

সুতরাং ধারাবাহিক ফলাফল তৈরি করার জন্য আপনার উপর নির্ভর করা উচিত নয়। এনক্রিপশনের জন্য, ফ্রেমওয়ার্ক আপনার নিজের ঘূর্ণায়মানের পরিবর্তে যে ক্লাসগুলি সরবরাহ করে তা ব্যবহার করুন।


10

কোডটি কীভাবে খারাপ তা সম্পর্কে প্রচুর উত্তর রয়েছে। তবে ফলাফলটি কেন অন্যরকম ...

অন্তর্বর্তী ফলাফলের জন্য আরও নির্ভুলতা পেতে ইন্টেলের এফপিইউগুলি অভ্যন্তরীণভাবে 80-বিট ফর্ম্যাটটি ব্যবহার করে । সুতরাং যদি কোনও মান প্রসেসরে রেজিস্ট্রারে থাকে তবে এটি 80 বিট পায়, তবে যখন এটি স্ট্যাকটিতে লেখা হয় তখন এটি 64 বিটে সংরক্ষণ করা হয় ।

আমি প্রত্যাশা করি। নেট এর নতুন সংস্করণটির জাস্ট ইন টাইম (জেআইটি) সংকলনে আরও ভাল অপটিমাইজার রয়েছে, সুতরাং এটি স্ট্যাকের কাছে লেখার চেয়ে স্ট্যাক থেকে আবার পড়ার চেয়ে কোনও রেজিস্টারে একটি মান রাখছে।

এটি হতে পারে যে জেআইটি এখন স্ট্যাকের পরিবর্তে কোনও রেজিস্ট্রারে একটি মূল্য ফেরত দিতে পারে। অথবা একটি রেজিস্টারে MOD ফাংশনে মানটি পাস করুন।

ওভারফ্লো প্রশ্ন স্ট্যাক এছাড়াও দেখুন একটি 80-বিট বর্ধিত নির্ভুলতা ডেটা ধরণের অ্যাপ্লিকেশন / সুবিধা কি?

অন্যান্য প্রসেসর, যেমন এআরএম এই কোডের জন্য বিভিন্ন ফলাফল দেবে।


6

কেবলমাত্র পূর্ণসংখ্যার গাণিতিক ব্যবহার করে এটি নিজেই গণনা করা ভাল। কিছুটা এইরকম:

int n = 143;
int e = 103;
int result = 1;
int ascii = (int) 'a';

for (i = 0; i < e; ++i) 
    result = result * ascii % n;

অন্যান্য উত্তরগুলিতে পোস্ট করা বিগইন্টেজার সমাধানের পারফরম্যান্সের সাথে আপনি পারফরম্যান্সটি তুলনা করতে পারেন।


7
এর জন্য 103 গুণ এবং মডুলাস হ্রাস প্রয়োজন। E2 = e * e% n, e4 = e2 * e2% n, e8 = e4 * e4% n, ইত্যাদি গণনা করে কেউ আরও ভাল করতে পারে এবং তারপরে ফলাফল = e * e2% n * e4% n * e32% n * e64% এন। মোট ১১ টি গুণ এবং মডুলাস হ্রাস। জড়িত সংখ্যার আকার বিবেচনা করে, কেউ আরও কয়েকটি মডুলাস হ্রাস দূর করতে পারে, তবে এটি 103 অপারেশন 11
সুপারক্যাট

4
@ সুপের্যাট চমৎকার গণিত, তবে অনুশীলনে কেবলমাত্র প্রাসঙ্গিক যদি আপনি এটি কোনও টোস্টারে চালাচ্ছেন।
alextgordon

7
@alextgordon: বা যদি কেউ বৃহত্তর ব্যয়কারী মানগুলি ব্যবহার করার পরিকল্পনা করে। ব্যাক্তিগত মানটিকে উদাহরণস্বরূপ 65521 তে প্রসারিত করতে যদি কেউ শক্তি হ্রাস ব্যবহার করে তবে 65,520 বিপরীতে যদি কেউ তা না করে তবে প্রায় 28 গুণ এবং মডুলাস হ্রাস লাগবে।
সুপারক্যাট

অ্যাক্সেসযোগ্য সমাধান দেওয়ার জন্য +1 যেখানে এটি গণনাটি কীভাবে করা হয় তা ঠিক clear
jwg

4
@ সুপের্যাট: আপনি একেবারে ঠিক বলেছেন। অ্যালগরিদমটি উন্নত করা সহজ, যা প্রাসঙ্গিক হয় যদি হয় তা খুব ঘন ঘন গণনা করা হয় বা উদ্দীপকগুলি বড় হয়। তবে মূল বার্তাটি হ'ল এটি পূর্ণসংখ্যার গাণিতিক ব্যবহার করে গণনা করা যেতে পারে এবং করা উচিত।
রোনাল্ড
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.