c# - डेल्फी में MidpointRounding.AwayFromZero के साथ Math.Round() के बराबर क्या है?
delphi delphi-7 (2)
आप जो देख रहे हैं, वह SimpleRoundTo साथ संयोजन में SimpleRoundTo फ़ंक्शन है। जैसा कि दस्तावेज कहते हैं:
SimpleRoundTo निकटतम मान लौटाता है जिसमें दस की निर्दिष्ट शक्ति होती है। यदि
AValue
दो निकटतम मूल्यों के बीच में है, जिसमें दस (ऊपर और नीचे) की निर्दिष्ट शक्ति है, तो यह फ़ंक्शन वापस आ जाता है:
AValue
पॉजिटिव होने पर प्लस इनफिनिटी की ओर वैल्यू।यदि
AValue
ऋणात्मक है और FPU गोलाई मोड rmUp पर सेट नहीं है, तो माइनस इनफिनिटी की ओर मान
ध्यान दें कि फ़ंक्शन का दूसरा पैरामीटर
TRoundToRange
जो .NET के
Math.Round
पद्धति में भिन्न डिगिसिस की संख्या के बजाय घातांक (10 की शक्ति) को संदर्भित करता है।
इसलिए 2 से 2 दशमलव स्थानों पर आप राउंड-टू रेंज का उपयोग करते हैं।
uses Math, RTTI;
var
LRoundingMode: TRoundingMode;
begin
for LRoundingMode := Low(TRoundingMode) to High(TRoundingMode) do
begin
SetRoundMode(LRoundingMode);
Writeln(TRttiEnumerationType.GetName(LRoundingMode));
Writeln(SimpleRoundTo(2.125, -2).ToString);
Writeln(SimpleRoundTo(-2.125, -2).ToString);
end;
end;
rmNearest
2,13
-2,13
rmDown
2,13
-2,13
rmUp
2,13
-2,12
rmTruncate
2,13
-2,13
मैं डेल्फी में
MidpointRounding.AwayFromZero
साथ c # समान
Math.Round
उपयोग कैसे करूं?
इसके बराबर क्या होगा:
double d = 2.125;
Console.WriteLine(Math.Round(d, 2, MidpointRounding.AwayFromZero));
आउटपुट:
2.13
डेल्फी में?
मेरा मानना है कि डेल्फी आरटीएल के SimpleRoundTo फ़ंक्शन अनिवार्य रूप से यह करता है, कम से कम अगर एफपीयू राउंडिंग मोड "सही" है। कृपया इसके प्रलेखन और कार्यान्वयन को ध्यान से पढ़ें, और फिर तय करें कि क्या यह आपके उद्देश्यों के लिए पर्याप्त है।
लेकिन सावधान रहें कि इस तरह के एकल राउंडिंग ऑपरेशन के लिए राउंडिंग मोड सेट करना एक स्थानीय समस्या को हल करने के लिए वैश्विक परिवर्तन का उपयोग कर रहा है। इससे समस्याएं (मल्टी-थ्रेडिंग, लाइब्रेरी आदि) हो सकती हैं।
बोनस बकबक: प्रश्न "नियमित" (पूर्णांक के लिए) गोलाई के बारे में था, मुझे लगता है कि मैंने एक दृष्टिकोण की कोशिश की थी
function RoundMidpAway(const X: Real): Integer;
begin
Result := Trunc(X);
if Abs(Frac(X)) >= 0.5 then
Inc(Result, Sign(X));
end;
बजाय।
बेशक, समान अंशों के सामान्य मामले के लिए भी समान फ़ंक्शन लिखना संभव है। (लेकिन सही ढंग से किनारे के मामलों, अतिवृष्टि, फ्लोटिंग-पॉइंट मुद्दों आदि को संभालने के लिए सावधान रहें।)
अद्यतन: मेरा मानना है कि निम्नलिखित चाल (और तेज है):
function RoundMidpAway(const X: Real): Integer; overload;
begin
Result := Trunc(X);
if Abs(Frac(X)) >= 0.5 then
Inc(Result, Sign(X));
end;
function RoundMidpAway(const X: Real; ADigit: integer): Real; overload;
const
PowersOfTen: array[-10..10] of Real =
(
0.0000000001,
0.000000001,
0.00000001,
0.0000001,
0.000001,
0.00001,
0.0001,
0.001,
0.01,
0.1,
1,
10,
100,
1000,
10000,
100000,
1000000,
10000000,
100000000,
1000000000,
10000000000
);
var
MagnifiedValue: Real;
begin
if not InRange(ADigit, Low(PowersOfTen), High(PowersOfTen)) then
raise EInvalidArgument.Create('Invalid digit index.');
MagnifiedValue := X * PowersOfTen[-ADigit];
Result := RoundMidpAway(MagnifiedValue) * PowersOfTen[ADigit];
end;
बेशक, यदि आप इस फ़ंक्शन को उत्पादन कोड में उपयोग करेंगे, तो आप कम से कम 50 यूनिट परीक्षण मामलों को भी जोड़ देंगे जो इसकी शुद्धता का परीक्षण करते हैं (दैनिक चलाने के लिए)।
अद्यतन: मेरा मानना है कि निम्नलिखित संस्करण अधिक स्थिर है:
function RoundMidpAway(const X: Real; ADigit: integer): Real; overload;
const
FuzzFactor = 1000;
DoubleResolution = 1E-15 * FuzzFactor;
PowersOfTen: array[-10..10] of Real =
(
0.0000000001,
0.000000001,
0.00000001,
0.0000001,
0.000001,
0.00001,
0.0001,
0.001,
0.01,
0.1,
1,
10,
100,
1000,
10000,
100000,
1000000,
10000000,
100000000,
1000000000,
10000000000
);
var
MagnifiedValue: Real;
TruncatedValue: Real;
begin
if not InRange(ADigit, Low(PowersOfTen), High(PowersOfTen)) then
raise EInvalidArgument.Create('Invalid digit index.');
MagnifiedValue := X * PowersOfTen[-ADigit];
TruncatedValue := Int(MagnifiedValue);
if CompareValue(Abs(Frac(MagnifiedValue)), 0.5, DoubleResolution * PowersOfTen[-ADigit]) >= EqualsValue then
TruncatedValue := TruncatedValue + Sign(MagnifiedValue);
Result := TruncatedValue * PowersOfTen[ADigit];
end;
लेकिन मैंने इसका पूरी तरह से परीक्षण नहीं किया है। (वर्तमान में यह 900+ यूनिट परीक्षण मामलों से गुजरता है, लेकिन मैं परीक्षण सूट को अभी तक पर्याप्त नहीं मानता हूं।)