फ़्लोटिंग पॉइंट नंबर को पूर्णांक में कैसे बदलें?


47

क्या यह बैश में पूर्णांक रूपांतरण के लिए फ्लोट करने का सही तरीका है? क्या कोई और तरीका है?

flotToint() {
    printf "%.0f\n" "$@"
}

5
क्या सही है"?
जोसेफ आर।

मैं सिर्फ यह सुनिश्चित करना चाहता हूं .. क्या यह सही है या क्या इससे बेहतर है?
राहुल पाटिल

2
%.0fऊपर या नीचे गोल होगा। क्या तुम यही चाहते हो? आप printf "%d\n" "$@" 2>/dev/nullअंश को काटने के लिए उपयोग कर सकते हैं ।
ott-- 23

जवाबों:


69

दे घुमा के

में bash, यह शायद उतना ही अच्छा है जितना यह हो जाता है। यह शेल शेल का उपयोग करता है। यदि आपको चर में परिणाम की आवश्यकता है, तो आप कमांड प्रतिस्थापन, या bashविशिष्ट (हालांकि अब भी समर्थित है zsh) का उपयोग कर सकते हैं :

printf -v int %.0f "$float"

तुम यह कर सकते थे:

float=1.23
int=${float%.*}

लेकिन यह है कि आप निकटतम पूर्णांक देने के बजाय आंशिक हिस्से को हटाने के हैं और उस के मूल्यों के लिए काम नहीं होगा $floatकी तरह 1.2e9या .12उदाहरण के लिए।

फ़्लोट्स के आंतरिक प्रतिनिधित्व के कारण संभावित सीमाओं पर भी ध्यान दें:

$ printf '%.0f\n' 1e50
100000000000000007629769841091887003294964970946560

आपको एक पूर्णांक नहीं मिलता है, लेकिन संभावना है कि आप उस पूर्णांक का उपयोग कहीं भी नहीं कर पाएंगे।

इसके अलावा, @BinaryZebra द्वारा, कई printfकार्यान्वयनों में (bash, ksh93, yash, GNU, zsh, डैश नहीं) द्वारा नोट किया गया , यह लोकेल (दशमलव विभाजक जो हो .या हो सकता है ,) से प्रभावित होता है ।

इसलिए, यदि आपकी फ़्लोट्स हमेशा दशमलव विभाजक के रूप में अवधि के साथ व्यक्त की जाती हैं और आप चाहते हैं कि printfआपकी लिपि को लागू करने वाले उपयोगकर्ता के लोकल की परवाह किए बिना इसे ऐसे ही माना जाए , तो आपको लोकेल को C पर ठीक करना होगा:

LC_ALL=C printf '%.0f' "$float"

इसके साथ yash, आप यह भी कर सकते हैं:

printf '%.0f' "$(($float))"

(निचे देखो)।

POSIX

printf "%.0f\n" 1.1

POSIX नहीं है क्योंकि POSIX %fद्वारा समर्थित होना आवश्यक नहीं है।

POSIXly, आप कर सकते हैं:

f2i() {
  awk 'BEGIN{for (i=1; i<ARGC;i++)
   printf "%.0f\n", ARGV[i]}' "$@"
}

यह कि लोकेल से प्रभावित नहीं है (अल्पविराम दशमलव विभाजक नहीं हो सकता awkक्योंकि यह पहले से ही वाक्य रचना में एक विशेष चरित्र है (जैसे print 1,2, print 1, 2दो तर्क पास करने के लिए print)

zsh

में zsh(जो फ़्लोटिंग पॉइंट अंकगणित (दशमलव विभाजक हमेशा की अवधि है) का समर्थन करता है), आपके पास rint()निकटतम पूर्णांक को एक फ्लोट (जैसे C) के रूप में देने के int()लिए और आपको एक फ्लोट (जैसे awk) से पूर्णांक देने के लिए गणित फ़ंक्शन है । तो आप कर सकते हैं:

$ zmodload zsh/mathfunc
$ i=$((int(rint(1.234e2))))
$ echo $i
123

या:

$ integer i=$((rint(5.678e2)))
$ echo $i
568

हालांकि ध्यान दें कि जबकि doubles बहुत बड़ी संख्या का प्रतिनिधित्व कर सकते हैं, पूर्णांक बहुत अधिक सीमित हैं।

$ printf '%.0f\n' 1e123
999999999999999977709969731404129670057984297594921577392083322662491290889839886077866558841507631684757522070951350501376
$ echo $((int(1e123)))
-9223372036854775808

ksh93

ksh93 फ्लोटिंग पॉइंट अंकगणित का समर्थन करने वाला पहला बॉर्न जैसा शेल था। ksh93 कमांड प्रतिस्थापन को एक पाइप का उपयोग करके या फोर्किंग का अनुकूलन करता है जब कमांड केवल अंतर्निहित कमांड होते हैं। इसलिए

i=$(printf '%.0f' "$f")

कांटा नहीं। या इससे भी बेहतर:

i=${ printf '%.0f' "$f"; }

जो या तो कांटा नहीं करता है, लेकिन नकली उप-वातावरण बनाने की सभी परेशानी नहीं करता है।

आप भी कर सकते हैं:

i=$((rint(f)))

लेकिन सावधान:

$ echo "$((rint(1e18)))"
1000000000000000000
$ echo "$((rint(1e19)))"
1e+19

आप भी कर सकते हैं:

integer i=$((rint(f)))

लेकिन इसके लिए पसंद करें zsh:

$ integer i=1e18
$ echo "$i"
1000000000000000000
$ integer i=1e19
$ echo "$i"
-9223372036854775808

उस ksh93फ़्लोटिंग पॉइंट अंकगणित को लोकेटर में दशमलव विभाजक सेटिंग का सम्मान करें (भले ही ,अन्यथा एक गणित ऑपरेटर है ( $((1,2))एक फ्रेंच / जर्मन ... लोकेल में 6/5 होगा, और $((1, 2))एक अंग्रेजी लोकेल में 2 है) ।

यश

यश फ़्लोटिंग पॉइंट अंकगणित का भी समर्थन करता है, लेकिन इसमें गणित के कार्य नहीं होते हैं जैसे ksh93/ zsh's rint()। आप उदाहरण के लिए बाइनरी या ऑपरेटर का उपयोग करके एक संख्या को पूर्णांक में बदल सकते हैं (यह भी काम करता है zshलेकिन अंदर नहीं ksh93)। ध्यान दें कि यह दशमलव भाग को काट देता है, यह आपको निकटतम पूर्णांक नहीं देता है:

$ echo "$((0.237e2 | 0))"
23
$ echo "$((1e19))"
-9223372036854775808

yash आउटपुट पर लोकेल के दशमलव विभाजक का सम्मान करता है, लेकिन इसके अंकगणितीय अभिव्यक्तियों में फ़्लोटिंग पॉइंट शाब्दिक स्थिरांक के लिए नहीं, जो आश्चर्य का कारण बन सकता है:

$ LC_ALL=fr_FR.UTF-8 ./yash -c 'a=$((1e-2)); echo $(($a + 1))'
./yash: arithmetic: `,' is not a valid number or operator

यह एक तरह से अच्छा है कि आप अपनी स्क्रिप्ट में फ़्लोटिंग पॉइंट कॉन्स्टेंट्स का उपयोग कर सकते हैं जो कि अवधि का उपयोग करते हैं और यह चिंता करने की ज़रूरत नहीं है कि यह अन्य स्थानों में काम करना बंद कर देगा, लेकिन फिर भी उपयोगकर्ता द्वारा व्यक्त की गई संख्याओं से निपटने में सक्षम हो जाएगा। जैसा कि आपको याद है:

var=$((10.3)) # and not var=10.3
... "$((a + 0.1))" # and not "$(($a + 0.1))".

printf '%.0f\n' "$((10.3))" # and not printf '%.0f\n' 10.3

int=${float%.*}मैक पर मेरे बैश (संस्करण 3.2.57 (1) -release) स्क्रिप्ट में बहुत अच्छा काम किया (संस्करण 10.13.4 (17E199))।
तेलमोनएगीसथस

आप पहली बार निर्माण जीएनयू बैश 4.4.19, जैसे में विफल रहता है: `` `$ गूंज $ अधिकतम 32.800 $ printf -v पूर्णांक% .0f" $ अधिकतम "बैश: printf: 32.800: अमान्य संख्या` ``
लुइस डी सूज़ा

@ LuísdeSousa, आपके स्थान पर शायद ,दशमलव मूलांक है। अनुभाग के बारे में देखेंLC_ALL=C
स्टीफन चेज़लस

ध्यान दें कि यह उत्तर एक अलग प्रश्न का उत्तर देता है: डॉट के बाद अंकों को कैसे निकालना है जो नहीं पूछा गया था: पूर्णांक करने के लिए फ्लोट करने का सही तरीका क्या है
आइजैक

क्या इस विधि को किसी भी संख्या में बिट्स के फ्लोट पर लागू किया जाना चाहिए? यह 23 बिट्स या 128 बिट्स मंटिसा के फ्लोट के लिए समान होना चाहिए?
इसहाक

21

bc - एक मनमाना सटीक कैलकुलेटर भाषा

int (फ्लोट) की तरह दिखना चाहिए:

$ echo "$float/1" | bc 
1234

इसका बेहतर उपयोग करने के लिए:

$ echo "($float+0.5)/1" | bc 

उदाहरण:

$ float=1.49
$ echo "($float+0.5)/1" | bc 
1
$ float=1.50
$ echo "($float+0.5)/1" | bc 
2

4
लेकिन float=-2; echo "($float+0.5)/1" | bcदेता है -1
स्टीफन चेज़लस

2
वह दौर को + inf की ओर कहा जाता है। वह चार संभावित तरीकों में से एक है ।

5

प्रस्तुत पिछला उत्तर लगभग सही था: "आप कर सकते थे:

float=1.23
int=${float%.*}

लेकिन यह आपको निकटतम पूर्णांक देने के बजाय भिन्नात्मक भाग को हटा देगा और उदाहरण के लिए $ee9 या .12 जैसे $ फ्लोट के मूल्यों के लिए काम नहीं करेगा। "

बस उपयोग करें ${float%%.*}

echo ${float%%.*}
1

3

एक बहुत ही सरल हैकी है

function float_to_int() { 
  echo $1 | cut -d. -f1    # or use -d, if decimals separator is ,
}

नमूना उत्पादन

$ float_to_int 32.333
32
$ float_to_int 32
32

यह उपयोग करना संभव होगा sed, लेकिन cutसमाधान सरल है। मैं पसंद करता हूं sedया cutजैसा कि वे एम्बेडेड लक्ष्य पर IMHO से अधिक उपलब्ध हैं awk(जो अभी भी की busyboxतुलना में काफी आम है bc)।
पाविक

0

सम्बंधित:

  1. कैसे जाग में पूर्णांक के लिए फ्लोट बनाते हैं ,
  2. शेल में फ्लोटिंग पॉइंट संख्या को गोल कैसे करें?

पूरक @ स्टीफन चेज़लस awk जवाब:

float_to_integer_rounding_nearst() {
    awk 'BEGIN{for (i=1; i<ARGC;i++) printf "%.0f", ARGV[i]}' "$@";
}

float_to_integer_rounding_floor() {
    awk 'BEGIN{for (i=1; i<ARGC;i++) printf "%d", int( ARGV[i] )}' "$@";
}

मेरे जागने पर, बाद वाला शून्य की ओर चक्कर लगाता है, माइनस इनफिनिटी के लिए नहीं (जैसा कि "मंजिल" का अर्थ लिया जा सकता है)। इसके अलावा, पहले दौर की संख्या भी आधी हो जाती है। मुझे यकीन नहीं है कि अगर यह बश printfकरता है, या यदि कोई अन्य कारण है तो बिलिन पर जागना पसंद करने से अलग है printf
ilkachachu
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.