2013-08-09 7 views
6

निम्नलिखित कोड में, गुणात्मक दृष्टिकोण क्यों गोलियों की त्रुटियों का उत्पादन नहीं कर रहा है, जबकि संचयी जोड़ दृष्टिकोण है?मुझे दो अनुमानित समान अंकगणितीय परिचालनों से अलग परिणाम क्यों मिलता है?

function get_value() { return 26.82; } 

function a($quantity) { 
    $value_excluding_vat = get_value(); 
    $value_including_vat = round($value_excluding_vat * (1 + (20/100)),2); 
    $total_nett = 0; 
    $total_gross = 0; 
    for($i=0; $i<$quantity; $i++) { 
     $total_nett += $value_excluding_vat; 
     $total_gross += $value_including_vat; 
    } 
    return array(
     $total_nett, 
     $total_gross 
    ); 
} 

function b($quantity) { 
    $value_excluding_vat = get_value(); 
    $value_including_vat = round($value_excluding_vat * (1 + (20/100)),2); 
    return array(
     $quantity * $value_excluding_vat, 
     $quantity * $value_including_vat 
    ); 
} 

$totals = a(1000); 
print_r($totals); 
echo $totals[1] - $totals[0]; 
echo "\n\n"; 
$totals = b(1000); 
print_r($totals); 
echo $totals[1] - $totals[0]; 

यहाँ मेरी उत्पादन है:

Array 
(
    [0] => 26820 
    [1] => 32180 
) 
5360.0000000005 

Array 
(
    [0] => 26820 
    [1] => 32180 
) 
5360 
+0

http के संभावित डुप्लिकेट: // stackoverflow। कॉम/प्रश्न/11366522/php-floating-point-error-with-basic-maths – BLaZuRE

+9

मैंने आपके प्रश्न को इस प्रकार पढ़ा है: _ "मेरे पास कोड ए (दिखाया नहीं गया था), जो फ़्लोटिंग पॉइंट नंबरों को गुणा करने और गोल करने पर परिणाम एक्स लौटा। मैंने इसे कोड बी (न तो दिखाया गया) में बदल दिया जो परिणाम उत्पन्न करता है वाई। ऐसा क्यों होता है? "_। जवाब है: यह आपके कोड पर निर्भर करता है, और शायद गोल करने वाली त्रुटियों के साथ करना है। कृपया अपना वास्तविक, प्रासंगिक कोड दिखाएं और आपने जो कोशिश की है। – CodeCaster

+0

[round()] (http://php.net/manual/en/function.round.php) के लिए $ मोड तर्क का उपयोग करने पर विचार करें: डिफ़ॉल्ट है PHP_ROUND_HALF_UP –

उत्तर

6

सबसे पहले अपने मामले में उपयोगी हो सकता है, पर विचार कई नंबर जो आधार 10 में तर्कसंगत हैं देखते हैं कि , लेकिन एक बाइनरी फ्लोटिंग बिंदु प्रतिनिधित्व में नहीं। उदाहरण के लिए, 26.82 का फ्लोटिंग पॉइंट वैल्यू वास्तव में 26.8200000000000002842170943040400743484497

स्वाभाविक रूप से, यदि आप इसे स्वयं जोड़ते रहते हैं तो कुछ त्रुटियां रेंगती हैं, लेकिन 15 महत्वपूर्ण अंक तक आपको ठीक होना चाहिए - यह 1000 बार जोड़ें और योग वास्तव में है 26819.9999999997671693563461303710937500000000

दिलचस्प सवाल यह है कि जब हम 1000.0 द्वारा एकाधिक 26.82 हमें 26820.0000000000000000000000000000000000000000 प्राप्त करते हैं - यह कैसे करता है?

जवाब नहीं है बस उस 26820.0 करता एक सटीक द्विआधारी प्रतिनिधित्व है, और गुणा आपरेशन बहुत चालाक है कि पहचानना है - भले 1001.0 से गुणा और 26.82 घटाकर अभी भी आप एक सटीक जवाब मिल जाएगा।

यहाँ कुछ दिलचस्प लिंक

  • http://www.h-schmidt.net/FloatConverter/ है - यह आप चल बिन्दु संख्या के एकल परिशुद्धता प्रतिनिधित्व को देखने की सुविधा देता है, और वास्तव में समझने तैरता
  • यह RFC on PHP rounding में उपयोगी हो सकता स्पर्शरेखीय दिलचस्प के रूप में यह शामिल किया गया है राउंडिंग आसपास के मुद्दों में से कुछ तैरता
  • और What Every Computer Scientist Should Know About Floating-Point Arithmetic
3

समस्या machine representation of float values में हो सकता है (चेतावनी ब्लॉक देखें)

उदा 21470.73 21470.729999..9994561 या 21470.73000 ... 00हो सकता है, इस पर निर्भर करता है कि उनकी गणना कैसे की गई थी। gross_total_so_far और nett_total_so_far की तरह अस्थायी मान पूर्णांक बनाना

प्रयास करें इससे पहले कि आप $total

1

मैं चल बिन्दु संख्या प्रतिनिधित्व और घटाव लेकिन की समस्या लगता है कि नहीं कर सकते,

गणना जब आप दौर के बिना इन मूल्यों को घटाना होगा आप का परिणाम प्राप्त होगा ** 3578.455

और जब आप इसे दो दशमलव बिंदु पर गोल करते हैं तो यह 3578.46 के साथ घूमता है।

तो php इस समस्या के साथ समाधान है।

PHP_ROUND_HALF_UP Round val up to precision decimal places away from zero, when it is half way there. Making 1.5 into 2 and -1.5 into -2. 

PHP_ROUND_HALF_DOWN  Round val down to precision decimal places towards zero, when it is half way there. Making 1.5 into 1 and -1.5 into -1. 

PHP_ROUND_HALF_EVEN  Round val to precision decimal places towards the next even value. 

PHP_ROUND_HALF_ODD Round val to precision decimal places towards the next odd value. 

ये निरंतर

echo round(100.675, 2, PHP_ROUND_HALF_UP); // 100.68 
echo round(100.675, 2, PHP_ROUND_HALF_DOWN); // 100.67 

रूप दौर समारोह के साथ आपूर्ति की जाती है तो PHP_ROUND_HALF_DOWN

संबंधित मुद्दे