"নির্বাচিত বিদ্যুৎ (10.0, 38.0)" কেন একটি গাণিতিক ওভারফ্লো ত্রুটি ফেলে দেয়?


15

আমি আমার IDENTITYওভারফ্লো চেক স্ক্রিপ্ট অ্যাকাউন্ট DECIMALএবং NUMERIC IDENTITYকলামগুলিতে আপডেট করছি ।

চেকটির অংশ হিসাবে আমি প্রতিটি IDENTITYকলামের জন্য ডেটা টাইপের সীমার আকার গণনা করি ; সেই পরিসরের কত শতাংশ শেষ হয়েছে তা গণনা করতে আমি এটি ব্যবহার করি। জন্য DECIMALএবং NUMERIC যে পরিসর আকার2 * 10^p - 2 যেখানে pস্পষ্টতা হয়।

আমি পরীক্ষাগুলি DECIMALএবং NUMERIC IDENTITYকলামগুলির সাথে একটি গুচ্ছ তৈরি করেছি এবং নীচে তাদের রেঞ্জগুলি গণনা করার চেষ্টা করেছি:

SELECT POWER(10.0, precision)
FROM sys.columns
WHERE 
       is_identity = 1
   AND type_is_decimal_or_numeric
;

এটি নিম্নলিখিত ত্রুটি ছুড়ে ফেলেছে:

Msg 8115, Level 16, State 6, Line 1
Arithmetic overflow error converting float to data type numeric. 

আমি এটিকে IDENTITYটাইপের কলামগুলিতে সংকুচিত করেছিলাম DECIMAL(38, 0)(যেমন সর্বাধিক নির্ভুলতার সাথে), তাই আমি তখন POWER()সেই মানটির উপর সরাসরি গণনাটি চেষ্টা করেছি ।

নীচের সমস্ত প্রশ্নের

SELECT POWER(10.0, 38.0);
SELECT CONVERT(FLOAT, (POWER(10.0, 38.0)));
SELECT CAST(POWER(10.0, 38.0) AS FLOAT);

একই ত্রুটির ফলস্বরূপ।

  • কেন SQL সার্ভার আউটপুট রূপান্তর করার চেষ্টা করে POWER(), টাইপ করা হয়, যা FLOAT, এর NUMERIC(বিশেষ করে যখন FLOATএকটি উচ্চ প্রাধান্য রয়েছে )?
  • সমস্ত সম্ভাব্য নির্ভুলতার জন্য ( অবশ্যই সহ ) আমি কীভাবে গতিশীলভাবে কোনও DECIMALবা NUMERICকলামের পরিসর গণনা করতে পারি p = 38?

উত্তর:


18

POWERডকুমেন্টেশন থেকে :

বাক্য গঠন

POWER ( float_expression , y )

যুক্তি

float_expression
একটি Is অভিব্যক্তি ধরনের ভাসা বা যে ধরনের পরোক্ষভাবে রূপান্তরিত করা যেতে পারে ভাসা

y
হ'ল শক্তি যা ভাসমান_প্রকাশ বাড়িয়ে তোলেy বিট ডেটা টাইপ বাদে সঠিক সংখ্যা বা আনুমানিক সংখ্যাসূচক ডেটা টাইপ বিভাগের একটি অভিব্যক্তি হতে পারে ।

রিটার্ন প্রকার

ফ্লোট_এক্সপ্রেশনে জমা দেওয়া একই ধরণের প্রত্যাবর্তন । উদাহরণস্বরূপ, যদি একটি দশমিক (2,0) ফ্লোট_এক্সপ্রেশন হিসাবে জমা দেওয়া হয়, তবে প্রাপ্ত ফলাফল দশমিক (2,0) হয়।


প্রথম ইনপুট স্পষ্টত প্রয়োজনে কাস্ট করা হয় float

অভ্যন্তরীণ গণনাটি floatস্ট্যান্ডার্ড সি রানটাইম লাইব্রেরি (সিআরটি) ফাংশন দ্বারা গাণিতিক ব্যবহার করে সঞ্চালিত হয় pow

এর পরে floatআউটপুটটি powবাম হাতের অপারেণ্ডের ধরণে ফিরে যায় ( numeric(3,1)আপনি যখন আক্ষরিক মান 10.0 ব্যবহার করেন তখন বোঝানো হবে )।

একটি সুস্পষ্ট ব্যবহার floatআপনার ক্ষেত্রে সূক্ষ্ম কাজ করে:

SELECT POWER(1e1, 38);
SELECT POWER(CAST(10 as float), 38.0);

10 38 এর সঠিক ফলাফলটি কোনও এসকিউএল সার্ভারে সংরক্ষণ করা যাবে না decimal/numericকারণ এটির জন্য 39 সংখ্যক নির্ভুলতার প্রয়োজন হবে (1 তার পরে 38 জিরো)। সর্বোচ্চ নির্ভুলতা 38।


23

মার্টিনের উত্তর নিয়ে আর কোনওভাবেই আলোচনার পরিবর্তে আমি POWER()এখানে আমার বাকী সমস্ত ফলাফল যুক্ত করব ।

আপনার নিকার্স ধরে রাখা।

প্রস্তাবনা

প্রথমে, আমি আপনার কাছে একটি, এমএসডিএন ডকুমেন্টেশন উপস্থাপন করছিPOWER() :

বাক্য গঠন

POWER ( float_expression , y )

যুক্তি

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

রিটার্ন প্রকার

হিসাবে একই float_expression

আপনি শেষ লাইনে যে POWER()রিটার্নের টাইপটি FLOATপড়েছেন তা শেষ করেই সিদ্ধান্ত নিতে পারেন , তবে আবার পড়ুন। float_expression"টাইপ ফ্লোট বা এমন এক ধরণের যা স্পষ্টতই ফ্লোটে রূপান্তরিত হতে পারে"। সুতরাং, এর নাম থাকা সত্ত্বেও, float_expressionএটি আসলে ক FLOAT, ক DECIMAL, বা একটি হতে পারে INT। আউটপুট যেহেতু POWER()একই float_expression, তাই এটিও এই ধরণেরগুলির মধ্যে একটি হতে পারে।

সুতরাং আমাদের কাছে রিটার্ন টাইপের সাথে একটি স্কেলার ফাংশন রয়েছে যা ইনপুটটির উপর নির্ভর করে। এটা হতে পারে?

পর্যবেক্ষণ

আমি উপস্থাপন আপনি বি, একটি পরীক্ষা প্রদর্শক প্রদর্শন করা POWER()তার ইনপুট উপর নির্ভর করে বিভিন্ন ধরনের তথ্য তার আউটপুট কাস্ট

SELECT 
    POWER(10, 3)             AS int
  , POWER(1000000000000, 3)  AS numeric0     -- one trillion
  , POWER(10.0, 3)           AS numeric1
  , POWER(10.12305, 3)       AS numeric5
  , POWER(1e1, 3)            AS float
INTO power_test;

EXECUTE sp_help power_test;

DROP TABLE power_test;

সম্পর্কিত ফলাফল:

Column_name    Type      Length    Prec     Scale
-------------------------------------------------
int            int       4         10       0
numeric0       numeric   17        38       0
numeric1       numeric   17        38       1
numeric5       numeric   17        38       5
float          float     8         53       NULL

কি মনে হচ্ছে, ঘটছে করা হয় POWER()কাস্ট float_expressionযে ফিট এটা সহ না ক্ষুদ্রতম ধরনের মধ্যে BIGINT

অতএব, SELECT POWER(10.0, 38);একটি ওভারফ্লো ত্রুটির সাথে ব্যর্থ হয় কারণ 10.0কাস্ট হয়ে যায় NUMERIC(38, 1)যা 10 38 এর ফলাফল ধরে রাখতে যথেষ্ট বড় নয় । কারণ 10 38 দশমিকের আগে 39 অঙ্ক নিতে প্রসারিত, যেখানে NUMERIC(38, 1)দশমিক প্লাস একের আগে 37 অঙ্ক সংরক্ষণ করতে পারে। অতএব, সর্বোচ্চ মানটি NUMERIC(38, 1)10 37 - 0.1 ধরে রাখতে পারে ।

এই বোঝার সাথে সজ্জিত হয়ে আমি নীচে আরও একটি ওভারফ্লো ব্যর্থতা কাটিয়ে উঠতে পারি।

SELECT POWER(1000000000, 3);    -- one billion

এক বিলিয়ন (প্রথম উদাহরণ থেকে এক ট্রিলিয়ন এর বিপরীতে, যা নিক্ষেপ করা হয় NUMERIC(38, 0)) কেবলমাত্র একটি এনে ফিট করার জন্য যথেষ্ট ছোট INT। তৃতীয় শক্তিতে উত্থাপিত এক বিলিয়ন, তবে এটির পক্ষে খুব বড় INT, অতএব ওভারফ্লো ত্রুটি।

অন্যান্য বেশ কয়েকটি ফাংশন অনুরূপ আচরণ প্রদর্শন করে, যেখানে তাদের আউটপুট টাইপ তাদের ইনপুটটির উপর নির্ভরশীল:

উপসংহার

এই বিশেষ ক্ষেত্রে, সমাধানটি ব্যবহার করা SELECT POWER(1e1, precision)...1e1কাস্টিং হয়ে যাওয়ার পরে এটি সমস্ত সম্ভাব্য নির্ভুলতার জন্য কাজ করবে FLOAT, যা হাস্যকরভাবে প্রচুর সংখ্যক ধরে রাখতে পারে ।

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

বাচ্চারা, এখন আপনি যে এটি জানেন, আপনি এগিয়ে এবং সমৃদ্ধ হতে পারে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.