حسابگر داخلی BASH فقط از اعداد صحیح استفاده میکند:
$ echo $((10/3)) 3
برای اکثر عملیات درگیر با اعداد دارای ممیزشناور، باید از یک برنامه خارجی استفاده شود، به عنوان نمونه از bc، AWK یا dc:
$ echo "scale=3; 10/3" | bc 3.333
فرمان "scale=3" به برنامه bc اعلام میکند که سه رقم دقت بعد از نقطه اعشاری لازم است.
همان مثال با dc( ماشین حساب شسته رفته و سبُکتر از bc):
$ echo "3 k 10 3 / p" | dc 3.333
k دقت اعشار را به 3 رقم تنظیم میکند، و p بالاترین قسمت پُشته را با یک کاراکتر سطر جدید چاپ میکند. به هر حال، پُشته جایگزین نمیشود.
اگر میخواهید اعداد اعشاری را مقایسه کنید(کوچکتر از، یا بزرگتر از) ، و bc گنو را دارید، میتوانید چنین کنید:
# Bash if (( $(bc <<< "1.4 < 2.5") )); then echo "1.4 is less than 2.5." fi
اما، x < y توسط تمام نگارشهای bc پشتیبانی نمیشود:
# خیر HP-UX 10.20 این با برخی نگارشها کار میکند اما با imadev:~$ bc <<< '1 < 2' syntax error on line 1,
اگر میخواهید قابل حمل باشید، به مورد ماهرانهتری نیاز دارید:
# POSIX case $(echo "1.4 - 2.5" | bc) in -*) echo "1.4 is less than 2.5";; esac
این مثال 2.5 را از 1.4 تفریق میکند، و علامت نتیجه را کنترل میکند.اگر منفی باشد، عدد اول کوچکتر از دومی است. در حقیقت، ما با خروجی bc به عنوان عدد رفتار نمیکنیم، با آن به صورت یک رشته رفتار میکنیم، و فقط به اولین کاراکتر آن نگاه میکنیم.
میراث نگارش (Bourne):
# Bourne case "`echo "1.4 - 2.5" | bc`" in -*) echo "1.4 is less than 2.5";; esac
AWK نیز میتواند برای محاسبات به کار برود:
$ awk 'BEGIN {printf "%.3f\n", 10 / 3}' 3.333
در اینجا تفاوت ظریف اما مهمی بین راه حل bc و awk وجود دارد: bc فرمانها و عبارات را از ورودی استاندارد میخواند. از طرف دیگر awk عبارت را به عنوان بخشی از برنامه برآورد میکند. عبارتها در ورودی استاندارد سنجیده نمیشوند، یعنی فرمان echo 10/3 | awk '{print $0}' به جای ارزیابی، نتیجه عبارت 10/3 را چاپ میکند.
نگارشهای جدیدتر پوسته zsh و پوسته Korn یک حساب ممیز شناور داخلی، همراه با توابعی مانند sin() یا cos() در خود دارند. بنابراین بسیاری از این محاسبات، در ksh میتوانند به طور بومی انجام شوند:
# ksh93 $ echo $((3.00000000000/7)) 0.428571428571428571
مقایسه برابری دو عدد با ممیز شناور ، در واقع کار نابخردانهای میباشد، دو محاسبهای که روی کاغذ نتیجه یکسانی ارائه خواهند داد ممکن است در نتایج عددی ممیز شناور تفاوت بسیار جزئی ناشی از گِرد کردن و کوتاهسازی نشان بدهد. اگر میخواهید تعیین کنید که آیا دو عدد با ممیز شناور یکسان هستند، میتوانید:
یک عدد را از دیگری تفریق نموده و مقدار خالص تفاضل را با مقدار ناچیزی به انتخاب خود مقایسه نمایید.
یکی از موارد بسیار اندکی که Bash به طور واقعی میتواند با اعداد ممیز شناور انجام بدهد، گرد نمودن آنها با استفاده از printf است:
# Bash 3.1 # به یکدیگر نزدیک باشند b و a ببینید اگر # گرد کردن آنها تا دو رقم اعشار و مقایسه نتایج به عنوان رشته را a=3.002 b=2.998 printf -v a1 %.2f $a printf -v b1 %.2f $b if [[ $a1 = "$b1" ]]; then echo "a and b are the same, roughly"; fi
پیشبینی احتیاطی: بسیاری از مشکلاتی که به محاسبات ممیز شناور شباهت دارند در حقیقت میتوانند فقط با اعداد صحیح حل بشوند، و بنابراین به این ابزارها نیازی نمیباشد-- به عنوان مثال، مشکلات مربوط به اعداد کسری. برای نمونه، جهت کنترل اینکه آیا نسبت دو عدد x و y، برابر با نسبت 4:3 یا 16:9 میباشد، میتوانید از موردی مشابه این سطرها استفاده کنید:
# Bash # Variables x and y are integers if (( $x*9-$y*16==0 )) ; then echo "16:9." elif (( $x*3-$y*4==0 )) ; then echo "4:3." else echo "Neither 16:9 nor 4:3." fi
در یک بررسی استادانهتر، بدون استفاده از محاسبات ممیز شناور، میتوانست تشخیص داده شود نزدیکترین نسبت 4:3 است یا 16:9. توجه نمایید که این مثال بسیار سادهای میباشد و ظاهراً اعداد ممیز شناور و تقسیم را در گیر میسازد، که با اعداد صحیح و بدون تقسیم حل میشود. اگر امکان داشته باشد، به طور معمول تبدیل مشکل شما به محاسبات صحیح، ثمربخشتر از به کار بردن محاسبات ممیز شناور است.
پرسش و پاسخ 22 (آخرین ویرایش ed 2012-11-26 10:07:41 توسط geirha)