টিএসকিউএল বিদ্যুৎ (2., return৪।) এর ভুল মানটি কেন দেয়?


14

select POWER(2.,64.)18446744073709552000পরিবর্তে ফিরে 18446744073709551616। মনে হচ্ছে এটি কেবল 16 সংখ্যক নির্ভুলতার (17 তম গোলাকার) রয়েছে।

এমনকি স্পষ্টতাকে স্পষ্ট করে তোলা select power(cast(2 as numeric(38,0)),cast(64 as numeric(38,0)))এটি গোলাকৃত ফলাফলটি দেয়।

এটি এটির মতো নির্ভুলতার 16 ডিজিটে স্বেচ্ছাসেবীভাবে বের হওয়ার জন্য এটি একটি দুর্দান্ত বেসিক অপারেশন বলে মনে হচ্ছে। এটি সঠিকভাবে গণনা করতে পারে সর্বোচ্চটি POWER(2.,56.)ব্যর্থ হয় POWER(2.,57.)। এখানে কি হচ্ছে?

আসলেই ভয়াবহটি হ'ল এটি select 2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.*2.;আসলে সঠিক মানটি দেয়। তৃষ্ণার জন্য তাই অনেক।


উত্তর:


17

থেকে অনলাইন ডকুমেন্টেশন :

POWER ( float_expression , y )  

যুক্তি

ফ্লোট_এক্সপ্রেসন হ'ল টাইপ ফ্লোট বা এমন এক ধরণের অভিব্যক্তি যা স্পষ্টতই ফ্লোটে রূপান্তরিত হতে পারে

প্রভাবটি হ'ল আপনি প্রথম পরামিতি হিসাবে যা যা করেন তা ফাংশনটি কার্যকর float(53) হওয়ার আগে স্পষ্টতই একটিতে ফেলে দেওয়া হবে। তবে, এটি (সর্বদা?) কেস নয়

যদি এটি হয় তবে এটি নির্ভুলতার ক্ষতি সম্পর্কে ব্যাখ্যা করবে:

দশমিক বা সংখ্যায় বৈজ্ঞানিক স্বরলিপি ব্যবহার করে এমন ভাসমান মানগুলির রূপান্তর কেবলমাত্র 17 অঙ্কের মানগুলিতে সীমাবদ্ধ। শূন্য থেকে 17 রাউন্ডের চেয়ে বেশি নির্ভুলতার সাথে কোনও মান।

অন্যদিকে, আক্ষরিক 2.টাইপ numeric…:

DECLARE @foo sql_variant;
SELECT @foo = 2.;
SELECT SQL_VARIANT_PROPERTY(@foo, 'BaseType');
GO
| (কোনও কলামের নাম নেই) |
| : --------------- |
| সংখ্যা |

এখানে ডিবিফিডল

… এবং গুণক অপারেটর আর্গুমেন্টের ডেটা টাইপকে উচ্চতর প্রাধান্য দিয়ে দেয়

এটি প্রদর্শিত হয় যে 2016 (এসপি 1) এ, সমস্ত নির্ভুলতা ধরে রাখা হয়েছে:

SELECT @@version;
GO
| (কোনও কলামের নাম নেই) |
| : ------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ------- |
| মাইক্রোসফ্ট এসকিউএল সার্ভার 2016 (এসপি 1) (কেবি 3182545) - 13.0.4001.0 (এক্স 64) <br> অক্টোবর 28 2016 18:17:30 <br> কপিরাইট (সি) মাইক্রোসফ্ট কর্পোরেশন <br> উইন্ডোজ সার্ভারে এক্সপ্রেস সংস্করণ (-৪-বিট) 2012 আর 2 স্ট্যান্ডার্ড 6.3 <X64> (9600 বিল্ড করুন:) (হাইপারভাইসর) <br> |
SELECT POWER(2.,64.);
GO
| (কোনও কলামের নাম নেই) |
| : ------------------- |
| 18446744073709551616 |

এখানে ডিবিফিডল

… তবে ২০১৪ (এসপি ২) এ তারা নেই:

SELECT @@version;
GO
| (কোনও কলামের নাম নেই) |
| : ------------------------------------------------- -------------------------------------------------- -------------------------------------------------- -------------------------------------------------- ------------------------------------ |
| মাইক্রোসফ্ট এসকিউএল সার্ভার 2014 (এসপি 2) (কেবি 3171021) - 12.0.5000.0 (এক্স 64) <br> জুন 17 2016 19:14:09 <br> কপিরাইট (সি) মাইক্রোসফ্ট কর্পোরেশন <br> উইন্ডোজ এনটি-তে এক্সপ্রেস সংস্করণ (-৪-বিট) 6.3 <X64> (9600 বিল্ড করুন:) (হাইপারভাইজার) <br> |
SELECT POWER(2.,64.);
GO
| (কোনও কলামের নাম নেই) |
| : ------------------- |
| 18446744073709552000 |

এখানে ডিবিফিডল


1
সুতরাং মূলত, POWER ফাংশন নির্ভুলতার 17 টিরও বেশি সংখ্যক প্রয়োজনের জন্য অনর্থক। এ কারণেই এটি সঠিক ফলাফল তৈরি করে POWER(2.,56.) = 72057594037927936তবে উচ্চতর হয় না। আমার ধারণা আমার নিজের পাওয়ার ফাংশনটি লিখতে হবে যা কেবল একটি লুপে লুপ হয়, লও।
ট্রায়ঙ্কো

14

2 of 64 এর ফলাফলটি float(এবং realসেই বিষয়ে) হুবহু উপস্থাপনযোগ্য ।

সমস্যা দেখা দেয় যখন এই সুনির্দিষ্ট ফলাফলটি আবার numeric(প্রথম POWERঅপারেন্ডের ধরণে) রূপান্তরিত হয় ।

আগে ডাটাবেসের সামঞ্জস্য স্তর 130 চালু করা হয়, এসকিউএল সার্ভার বৃত্তাকার floatথেকে numeric17 ডিজিটের সর্বাধিক অন্তর্নিহিত ধর্মান্তর।

সামঞ্জস্যতা স্তরের ১৩০ এর অধীনে, রূপান্তরকালে যতটা সম্ভব নির্ভুলতা সংরক্ষণ করা হবে। এটি নলেজ বেস প্রবন্ধে নথিভুক্ত করা হয়েছে:

কিছু ডেটা ধরণের এবং অস্বাভাবিক ক্রিয়াকলাপ পরিচালনার ক্ষেত্রে এসকিউএল সার্ভার 2016 উন্নতি

অ্যাজুরে এসকিউএল ডেটাবেসগুলিতে এটির সুবিধা নিতে COMPATIBILITY_LEVELআপনাকে 130 এ সেট করতে হবে:

ALTER DATABASE CURRENT SET COMPATIBILITY_LEVEL = 130;

কাজের চাপ পরীক্ষা করা দরকার কারণ নতুন ব্যবস্থাটি কোনও প্যানিসিয়া নয়। উদাহরণ স্বরূপ:

SELECT POWER(10., 38);

... একটি ত্রুটি নিক্ষেপ করা উচিত কারণ 10 38 টি সংরক্ষণ করা যায় না numeric(38 এর সর্বোচ্চ নির্ভুলতা)। একটি ওভারফ্লো ত্রুটিটি 120 সামঞ্জস্যের অধীনে ফলাফল, তবে 130 এর নীচে ফলাফলটি:

99999999999999997748809823456034029568 -- (38 digits)

2

একটি সামান্য গণিত সঙ্গে আমরা একটি workaround খুঁজে পেতে পারেন। বিজোড় জন্য n:

2 ^ n 
= 2 ^ (2k + 1)
= 2 * (2 ^ 2k)
= 2 * (2 ^ k) * (2 ^ k)

এমনকি n:

2 ^ n 
= 2 ^ (2k)
= 1 * (2 ^ 2k)
= 1 * (2 ^ k) * (2 ^ k)

এটি টি-এসকিউএলে লেখার একটি উপায়:

DECLARE @exponent INTEGER = 57;

SELECT (1 + @exponent % 2) * POWER(2., FLOOR(0.5 * @exponent)) * POWER(2., FLOOR(0.5 * @exponent));

এসকিউএল সার্ভার ২০০৮-তে পরীক্ষিত, ফলাফল 144115188075855872 এর পরিবর্তে 144115188075855870।

এটি 113 এর ঘাটতি পর্যন্ত সমস্তভাবে কাজ করে It মনে হয় যে একটি NUMERIC (38,0) 2 ^ 126 পর্যন্ত সঞ্চয় করতে পারে তাই যথেষ্ট পূর্ণ কভারেজ নেই, তবে প্রয়োজনে সূত্রটি আরও টুকরো টুকরো হয়ে যেতে পারে could ।


0

কেবল মজাদার জন্য, একটি পুনরাবৃত্ত সিটিই সমাধান:

with 
  prm (p, e) as           -- parameters, to evaluate: p**e
    (select 2, 64),       -- (2 ** 64)  
  pow (power, exp) as 
    (select cast(p as numeric(30,0)), 
            e
     from prm 
     union all 
     select cast(power * power * (case when exp % 2 = 0 then 1 else p end) 
                 as numeric(30,0)), 
            exp / 2 
     from prm, pow 
     where exp > 1 
    ) 
select power 
from pow 
where exp = 1 ;
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.