awk उच्च परिशुद्धता अंकगणित


11

मैं एक प्रतिस्थापन ऑपरेशन में उच्च परिशुद्धता अंकगणित करने के लिए awk बताने का एक तरीका ढूंढ रहा हूं। इसमें फ़ाइल से फ़ील्ड पढ़ना और उस मान पर 1% वृद्धि के साथ प्रतिस्थापित करना शामिल है। हालांकि, मैं वहाँ सटीक खो रहा हूँ। यहाँ समस्या का एक सरल प्रजनन है:

 $ echo 0.4970436865354813 | awk '{gsub($1, $1*1.1)}; {print}'
   0.546748

यहाँ, मेरे पास दशमलव सटीकता के बाद 16 अंक है लेकिन awk केवल छह देता है। प्रिंटफ का उपयोग करके, मुझे वही परिणाम मिल रहा है:

$ echo 0.4970436865354813 | awk '{gsub($1, $1*1.1)}; {printf("%.16G\n", $1)}'
0.546748

वांछित सटीकता प्राप्त करने के बारे में कोई सुझाव?


शायद awk में उच्च रिज़ॉल्यूशन है, लेकिन यह सिर्फ आपके आउटपुट स्वरूपण को छोटा कर रहा है। प्रिंटफ का प्रयोग करें।
संदिग्ध

प्रिंटफ का उपयोग करने के बाद परिणाम मूल्य में कोई बदलाव नहीं। तदनुसार संपादित किया गया प्रश्न।
एमके

जैसा कि @manatwork ने बताया है, gsubयह अनावश्यक है। समस्या gsubस्ट्रिंग्स पर काम करती है, संख्याओं पर नहीं, इसलिए पहले रूपांतरण का उपयोग किया जाता है CONVFMT, और उसके लिए डिफ़ॉल्ट मान है %.6g
15:16 बजे jw013

@ jw013, जैसा कि मैंने प्रश्न में उल्लेख किया है, मेरी मूल समस्या में gsub की आवश्यकता है क्योंकि मुझे 1% वेतन वृद्धि के साथ एक संख्या को प्रतिस्थापित करने की आवश्यकता है। सहमत, सरलीकृत उदाहरण में, इसकी आवश्यकता नहीं है।
एमके

जवाबों:


12
$ echo 0.4970436865354813 | awk -v CONVFMT=%.17g '{gsub($1, $1*1.1)}; {print}'
0.54674805518902947

या यहाँ बल्कि:

$ echo 0.4970436865354813 | awk '{printf "%.17g\n", $1*1.1}'
0.54674805518902947

शायद सबसे अच्छा आप प्राप्त कर सकते हैं। bcमनमानी परिशुद्धता के बजाय उपयोग करें ।

$ echo '0.4970436865354813 * 1.1' | bc -l
.54674805518902943

यदि आप चाहते हैं कि आप मनमाने ढंग से परिशुद्धता का AWKइस्तेमाल कर सकें तो -Mझंडे का इस्तेमाल कर सकते हैं और PRECबड़ी संख्या में मूल्य निर्धारित कर सकते हैं
रॉबर्ट बेन्सन

3
@RobertBenson, केवल GNU अवेक के साथ और केवल हाल के संस्करणों के साथ (4.1 या इसके बाद के संस्करण, इसलिए उस समय उत्तर नहीं लिखा गया था) और केवल जब MPFR को संकलित समय में सक्षम किया गया था।
स्टीफन चेज़लस

2

(GNU) awk (संकलित संकलित) के साथ उच्च परिशुद्धता के लिए उपयोग करें:

$ echo '0.4970436865354813' | awk -M -v PREC=100 '{printf("%.18f\n", $1)}'
0.497043686535481300

PREC = 100 का अर्थ है डिफ़ॉल्ट 53 बिट्स के बजाय 100 बिट्स।
यदि वह जागना उपलब्ध नहीं है, तो bc का उपयोग करें

$ echo '0.4970436865354813*1.1' | bc -l
.54674805518902943

या फिर आपको तैरने की अंतर्निहित अक्षमता के साथ जीना सीखना होगा।


आपकी मूल पंक्तियों में कई मुद्दे हैं:

  • 1.1 का एक कारक 10% की वृद्धि है, न कि 1% (1.01 गुणक होना चाहिए)। मैं 10% का उपयोग करूँगा।
  • CONVFMT द्वारा एक स्ट्रिंग से एक (फ्लोटिंग) संख्या में रूपांतरण प्रारूप दिया गया है। इसका डिफ़ॉल्ट मान है %.6g। यह मानों को 6 दशमलव अंकों (डॉट के बाद) तक सीमित करता है। के gsub परिवर्तन के परिणाम पर लागू होता है $1

    $ a='0.4970436865354813'
    $ echo "$a" | awk '{printf("%.16f\n", $1*1.1)}'
    0.5467480551890295
    
    $ echo "$a" | awk '{gsub($1, $1*1.1)}; {printf("%.16f\n", $1)}'
    0.5467480000000000
  • Printf प्रारूप gट्रेलिंग शून्य हटाता है:

    $ echo "$a" | awk '{gsub($1, $1*1.1)}; {printf("%.16g\n", $1)}'
    0.546748
    
    $ echo "$a" | awk '{gsub($1, $1*1.1)}; {printf("%.17g\n", $1)}'
    0.54674800000000001

    दोनों मुद्दों को हल किया जा सकता है:

    $ echo "$a" | awk '{printf("%.17g\n", $1*1.1)}'
    0.54674805518902947

    या

    $ echo "$a" | awk -v CONVFMT=%.30g '{gsub($1, $1*1.1)}; {printf("%.17f\n", $1)}'
    0.54674805518902947 

लेकिन विचार नहीं है कि इसका मतलब उच्च परिशुद्धता है। आंतरिक संख्या प्रतिनिधित्व अभी भी डबल आकार में एक फ्लोट है। इसका मतलब है कि 53 बिट्स की सटीकता और इसके साथ आप केवल 15 सही दशमलव अंकों के बारे में सुनिश्चित हो सकते हैं, भले ही कई बार 17 अंकों तक सही दिखें। वह मृगतृष्णा है।

$ echo "$a" | awk -v CONVFMT=%.30g '{gsub($1, $1*1.1}; {printf("%.30f\n", $1)}'
0.546748055189029469325134868996

सही मूल्य है:

$ echo "scale=18; 0.4970436865354813 * 1.1" | bc
.54674805518902943

यदि गणना ग्रंथि पुस्तकालय में संकलित की गई है, तो इसकी गणना (GNU) के साथ भी की जा सकती है:

$ echo "$a" | awk -M -v PREC=100 -v CONVFMT=%.30g '{printf("%.30f\n", $1)}'
0.497043686535481300000000000000
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.