Làm cách nào để in pi (3.14159)? [đóng cửa]


35

Lệnh nào có thể in pi cho tôi? Tôi muốn chỉ định có bao nhiêu chữ số in, tôi không thể tìm thấy bất cứ điều gì trực tuyến. Tôi chỉ muốn có thể in pi.


28
Hãy lựa chọn ngôn ngữ: rosettacode.org/wiki/Pi
Mark Plotnick

4
Lưu ý rằng sẽ vui hơn nếu bạn muốn có nhiều chữ số hơn khoảng 15.
Thorbjørn Ravn Andersen

2
@DisplayName: có nghĩa là bạn không còn có thể sử dụng bất kỳ chương trình nào lưu trữ / tính toán PI bên trong bằng cách sử dụng các giá trị dấu phẩy động chính xác kép (thường là loại dữ liệu FP "tích hợp" có độ chính xác cao nhất có sẵn trong hầu hết các ngôn ngữ).
Matteo Italia

5
Giải pháp của tôi, từ nhiều thập kỷ trước trước đây thường được các thư viện ngôn ngữ cung cấp, là ghi nhớ nó đến nhiều nơi hơn các điểm nổi mà tôi đang sử dụng sẽ cần: 3.1415926535897932384626 thường đủ gần cho các mục đích thực tế và thậm chí là hầu hết không thực tế -world sẽ có nhiều lỗi hơn so với các số khác và theo lý thuyết tôi sẽ gắn bó với giá trị biểu tượng hơn là giá trị số.
keshlam

3
@syntaxerror quan tâm là không liên quan. Nếu bạn đăng một câu hỏi yêu cầu chụp ảnh khỏa thân của những người nổi tiếng, nó sẽ nhận được hàng ngàn lượt xem và hoàn toàn có thể nâng cấp. Điều đó không làm cho nó về chủ đề. Câu hỏi này là một ví dụ cổ điển của quá rộng. Chỉ cần nhìn vào số lượng câu trả lời. Cũng lưu ý rằng OP đã không chỉ định bất kỳ giới hạn nào làm cho các câu trả lời có thể về cơ bản là vô hạn. Trong mọi trường hợp, đóng cửa không xóa. Câu hỏi và tất cả 23 câu trả lời của nó sẽ vẫn ở đây. Đóng chỉ có nghĩa là không có câu trả lời nữa được chấp nhận. Chúng ta có thực sự cần nhiều cách hơn để in π không?
terdon

Câu trả lời:


52

Bạn có thể sử dụng lệnh này:

echo "scale=5; 4*a(1)" | bc -l
3.14159

Trong đó tỷ lệ là số chữ số sau dấu thập phân.

Tham khảo: http://www.tux-planet.fr/calculer-le-chiffre-pi-en-ligne-de-commande-sous-linux/


12
Phiên bản ngắn hơn trong bashvà các shell khác hỗ trợ chuỗi ở đây : bc -l <<< "scale=5; 4*a(1)".
pabouk

2
Tôi tự hỏi có bao nhiêu chữ số này có thể đi?
DisplayName

4
@DisplayName khá ít. scale=1000cung cấp 999 chữ số chính xác khá nhanh chóng (chữ số cuối cùng tắt đi 1, hợp lý vì chúng tôi đang tính toán pi / 4 và sau đó nhân với 4). scale=4000đưa ra 4000 chữ số chính xác trong vài giây. scale=10000mất nhiều thời gian hơn tôi có kiên nhẫn, nhưng có thể đưa ra 9999 hoặc 10000 chữ số chính xác.
Hobbs

4
Điều này cho kết quả không chính xác trên máy của tôi, nhập 'echo "scale = 5; 4 * a (1)" | bc -l 'trả về 3.14156, khi chữ số cuối cùng bằng 9
Jordan Bentley


61

Nếu bạn đã tex(1)cài đặt:

tex --version | head -1 | cut -f2 -d' '

13
Điều này gần như đáng giá một upvote chỉ vì thông minh. Mặc dù đầu ra của điều này thay đổi khi bạn nâng cấp gói. Chúng ta sẽ coi đó là một tính năng hay một lỗi?
một CVn

8
@ MichaelKjorling Trên thực tế, nó thay đổi thành một xấp xỉ chính xác hơn của pi.
Abrixas2

@ Abrixas2 Vâng, tôi biết. Với phiên bản cuối cùng của TeX là phiên bản π.
một CVn

30
@DavidR Richby Ít chữ số hơn có thể được in thông qua một lệnh gọi bổ sung cut. Nhiều chữ số có thể được in bằng cách chờ đợi một thời gian dài và chạy lại lệnh.
Steven D

1
@Ruslan phụ thuộc vào việc thực hiện. Tôi hy vọng trong trường hợp cụ thể này sẽ được thực hiện "đúng".
Thorbjørn Ravn Andersen

23

Để in với độ chính xác tùy ý, bạn có thể sử dụng bcvà công thức pi = 4*atan(1):

# bc -l
scale=<your precision>
4*a(1)

2
Có một cái gì đó buồn cười về scaletùy chọn, pi = 3.141592..nhưng với echo "scale=5; 4*a(1)" | bc -l => 3.14156tôi sau đó tôi sẽ thấy 3.14159?
fduff

7
scalechỉ định độ chính xác để sử dụng để tính toán, do đó scale=5, không có hoạt động nào sẽ sử dụng nhiều hơn năm chữ số phân số cho bất kỳ hoạt động nguyên tử nào.
Abrixas2


20

Nếu bạn muốn một cái gì đó có thể tính giá trị của π, thì có một số cách tiếp cận. Có lẽ giải pháp rõ ràng nhất là sử dụng gói được tạo sẵn như pi(liên kết gói Debian) , nếu mô tả gói của Debian đáng tin cậy có thể tính giá trị theo độ chính xác tùy ý, chỉ giới hạn bởi bộ nhớ.

pithực sự là một ví dụ được bao gồm trong thư viện CLN (Thư viện lớp cho số) . Nó bao gồm các ứng dụng ví dụ cung cấp các công cụ để tạo các số có độ dài tùy ý như Pi, Fibonacci, v.v. Các gói CLN có sẵn được đóng gói sẵn trong Debian / Ubuntu (đó là những gì liên kết Debian ở trên đang trỏ đến).

Ví dụ
$ ./pi 10
3.141592653

$ ./pi 20
3.1415926535897932384

LƯU Ý: Nguồn của các ví dụ này có ở đây trong nguồn cho cơ sở mã CLN .

Các bản phát hành khác

Fedora

Trên Fedora tôi đã phải tải tarball nguồn và tự xây dựng nó, nhưng nó xây dựng với một chút phiền phức. Vì bất kỳ lý do gì, gói clntrên Fedora chỉ bao gồm thư viện nhưng bỏ qua các ví dụ có sẵn trong phiên bản Debian / Ubuntu (ở trên).

Cổng vòm

Arch cung cấp các chương trình tương tự trong các clngói (nhờ Amphiteót ).


Vâng, heh tôi có nghĩa là tổng giá trị tôi vừa gõ những gì tôi có trong đầu.
DisplayName

2
"Tổng giá trị" ?? Nghĩa là gì...?
Kyle Strand

2
@DisplayName đọc phần còn lại của câu trả lời. Một chương trình dành riêng như piâm thanh giống như chính xác những gì bạn đang tìm kiếm. Bạn có thể làm những việc như pi 300in 300 chữ số đầu tiên chẳng hạn.
terdon

3
@KyleStrand Tôi đã phát hiện ra một câu trả lời thực sự tuyệt vời cho điều đó, mà nhận xét này quá hẹp để chứa. Này, nó đã làm việc cho Fermat !
terdon

Tôi rất muốn biết lý do tại sao điều này đã nhận được hai downvote. Có phải những người đã đánh giá thấp đã không đọc câu trả lời trước khi họ quyết định rằng nó không hữu ích?
một CVn

17

Để có tới một triệu chữ số, bạn có thể sử dụng như sau (ở đây cho 3000 chữ số):

curl --silent http://www.angio.net/pi/digits/pi1000000.txt | cut -c1-3000

2
Điều này có lợi ích bổ sung là nó phải gần hợp lý với độ phức tạp O (1). Hoặc có lẽ đó không phải là một lợi ích sau tất cả ...
CVn

7
Ngoài ra, thật khó để nói rằng bất kỳ tương tác mạng nào là độ phức tạp thời gian O (1) trong một thế giới thực tế. : P
HalosGhost

2
@HalosGhost Đối với mục đích của chúng tôi (so với tính toán n chữ số pi mỗi lần), việc tải xuống một lượng dữ liệu cố định từ một máy chủ cụ thể qua mạng có thể có hiệu quả là O (1), trong khi tính toán n chữ số của pi có thể là ít nhất là một cái gì đó như O (log n) và hoàn toàn có thể cao hơn (tôi không quen với các thuật toán đó). Việc tải xuống dữ liệu thực tế có thể sẽ mất nhiều thời gian hơn so với chi phí để bắt đầu tải xuống, do đó thời gian tải xuống chiếm ưu thế và bạn nhận được một nơi nào đó trong vùng lân cận của O (1) với tốc độ truyền dữ liệu cố định hợp lý. Do đó O (1).
một CVn

4
@ MichaelKjorling Khi bạn nói O (1) không thực sự bạn có nghĩa là O (n)? Thời gian tải xuống theo tuyến tính theo số chữ số bạn cần, do đó O (n).
CodeInChaos

1
@CodesInChaos Không, thời gian tải xuống không đổi (tốc độ truyền không đổi) vì bạn đang tải xuống một số chữ số không đổi (một triệu, tại đây). Trừ khi (trong trường hợp cụ thể này) curl đủ thông minh để in trong khi tải xuống và dừng tải xuống sau khi đường ống bị vỡ vì cutthoát? Nếu đó là trường hợp, tôi đồng ý, nó sẽ là O (n).
một CVn

15

Một số câu trả lời khác hiển thị chữ số không chính xác ở vị trí cuối cùng của đầu ra. Dưới đây là một biến thể của câu trả lời bằng cách sử dụngbc nhưng với kết quả được làm tròn chính xác. Biến schứa số chữ số có nghĩa (bao gồm 3ở phía trước dấu thập phân).

Làm tròn một nửa

$ bc -l <<< "s=5; scale=s+2; pi=4*a(1)+5*10^(-s); scale=s-1; pi/1"
3.1416

Làm tròn xuống (cắt ngắn)

$ bc -l <<< "s=5; scale=s+2; pi=4*a(1); scale=s-1; pi/1"
3.1415

Giải thích về làm tròn

Việc làm tròn được thực hiện trực tiếp trong bc. Điều này không có giới hạn của lệnh printfsử dụng biểu diễn doubleloại ngôn ngữ C cho các số có độ chính xác khoảng 17 chữ số có nghĩa. Xem câu trả lời với printflàm tròn .

scale=s-1đặt số lượng chữ số để cắt ngắn. pi/1chia kết quả cho 1 để áp dụng cắt ngắn. Đơn giản pikhông cắt bớt số.

Làm tròn một nửa yêu cầu thêm 5 vào chữ số đầu tiên sẽ bị cắt (5 × 10 -s ) để trong trường hợp các chữ số cao hơn bằng 5, chữ số cuối sẽ còn lại sẽ được tăng lên.

Từ các bài kiểm tra của hobbs , dường như ba chữ số bổ sung sẽ được làm tròn / cắt ( scale=s+2) sẽ đủ ngay cả đối với các số rất dài.

Đây

Những ví dụ trên sử dụng ở đây chuỗi được hỗ trợ ví dụ như trong bash, kshzsh. Nếu shell của bạn không hỗ trợ ở đây, sử dụng chuỗi echovà đường ống thay thế:

$ echo "s=5; scale=s+2; pi=4*a(1); scale=s-1; pi/1" |  bc -l
3.1415

2
Tính toán ba chữ số bổ sung cho mục đích làm tròn không phải là cách làm tròn chính xác như bạn yêu cầu trong một nhận xét. Đầu tiên, bạn không bị ràng buộc về lỗi tính toán. Nếu nó có thể bị sai bởi 3 đơn vị ở vị trí cuối cùng theo yêu cầu của fduff, tại sao nó không bị sai bởi 1000 đơn vị ở vị trí cuối cùng? Thứ hai, hãy xem tiến độ tiến thoái lưỡng nan của nhà sản xuất bảng.
Biến chứng xem sinh học

12

perl một dòng (sử dụng bignum ):

perl -Mbignum=bpi -wle 'print bpi(NUM)'

ví dụ

perl -Mbignum=bpi -wle 'print bpi(6)'
3.14159

Đối với 10.000 chữ số: Gần 8 phút tính theo perl, dưới 4 trong bc. Không phải là nhanh nhất.
Isaac

9

Với python2:

$ python -c "import math; print(str(math.pi)[:7])"
3.14159

4
Để hoàn thiện, giải pháp này dành riêng cho python2.
HalosGhost

Sau khi chỉnh sửa, với (..)điều này hoạt động trong Python 2 và 3. Chỉ có 12 chữ số.
Anthon

$ Python -c "toán nhập khẩu; in (định dạng (Math.PI, '.400f'))" 3,1415926535897931159979634685441851615905761718750000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Artem Shitov

1
@ArtemShitov - xấu của tôi, hãy thử nhập gmpy2 (nếu bạn đã cài đặt nó) : python -c "import gmpy2; print(str(gmpy2.const_pi(8192))[:400])". Tăng độ chính xác để biết thêm chữ số ... ví dụpython -c "import gmpy2; print(str(gmpy2.const_pi(16384))[:4400])"
don_crissti

1
Nhanh nhất tôi có thể tìm thấy from mpmath import mp; mp.dps = 1000000 ; print(mp.pi)chỉ là một vài giây cho một triệu chữ số. Không xấu cả !!!.
Isaac

7

Sử dụng Ruby:

require "bigdecimal"
require "bigdecimal/math"
include BigMath

BigDecimal(PI(100)).round(9).to_s("F")

3.141592654

1
Một lớp lót:ruby -e 'require "bigdecimal"; require "bigdecimal/math"; include BigMath; puts BigDecimal(PI(100)).round(9).to_s("F")'

4

Trong bash:

$ read -a a <<< $(grep M_PIl /usr/include/math.h) ; echo ${a[3]} | tr -d L
3.141592653589793238462643383279502884

@ Amphiteóth afmtodityêu cầu groffphải được cài đặt. Ở đây trên Ubuntu (& hương vị), nó không chuẩn. JFYI.
cú pháp

@syntaxerror Cảm ơn bạn, điểm tốt! Tôi đã loại bỏ ví dụ của tôi. Quan điểm của tôi là khi đọc AI này chạy greptrên hệ thống của tôi, tìm kiếm hằng số và tìm thấy nó ở nhiều nơi. Đó là lý do tại sao đây là +1 đối với tôi!

3

Rất đơn giản trong PHP bằng cách sử dụng hàm pi () tích hợp:

<?php 
echo round(pi(), 2);
?>

1
Bạn có thể chỉnh sửa điều này để đưa ra một phiên bản dòng lệnh?
tò mò

3

Làm thế nào tôi bỏ lỡ câu hỏi này ...

Đây là một chương trình Python pi nhỏ của tôi mà tôi đã đăng vài tuần trước trên Stack Overflow. Nó không đặc biệt nhanh, nhưng nó có thể tạo ra rất nhiều chữ số. :) Tuy nhiên, như tôi đã đề cập trong chủ đề đó, tôi thường sử dụng mô đun mpmath của Python cho số học chính xác tùy ý và mpmath có một trình tạo pi khá nhanh.

Ví dụ,

time python -c "from mpmath import mp;mp.dps=500000;print mp.pi" >bigpi

real    0m4.709s
user    0m4.556s
sys     0m0.084s

IMHO 500000 số thập phân dưới 5 giây không quá tồi tệ, IMHO, xem xét nó chạy trên một máy có bộ xử lý 2 GHz lõi đơn, 2 GB RAM và ghi vào ổ đĩa IDE cũ.


Hãy thử from mpmath import mp; mp.dps = 1000000 ; print(mp.pi)(sau khi cài đặt pip3 mpmath) dưới hai giây cho một triệu chữ số. Không xấu cả !!!.
Isaac

2

Nếu bạn đã node.jscài đặt, điều này sẽ làm hết sức mình trong việc tìm kiếm pi cho bạn, mặc dù điều tốt nhất của nó không phải là rất tốt:

node -e 'for(a=0,b=4E8,m=Math,r=m.random;b--;)a+=(1>m.sqrt((c=r())*c+(d=r())*d));console.log(a/1E8)'

Đầu ra mẫu:

3.14157749
3.1416426
3.14159055
3.14171554
3.14176165
3.14157587
3.14161137
3.14167685
3.14172371

4
Ngắn hơn node -e 'console.log(Math.PI)'là một chút tốt hơn so với tốt nhất của nó.
chbrown

1
@chbrown Điều đó không thỏa mãn yêu cầu "không nghiêm trọng" của OP.
Paul

1
Yêu cầu "không nghiêm trọng" là gì? OP chỉ tuyên bố rằng họ đang yêu cầu sự vui vẻ không phải là họ muốn câu trả lời nào đó "không nghiêm trọng". Điều đó có nghĩa là gì? Một cái gì đó như thế echo pienào?
terdon

Tôi đã gõ nó bởi vì khi bạn đặt câu hỏi đôi khi người ta nói rằng "đây không phải là nhà máy viết kịch bản", vì vậy tôi nói rằng vì không có lý do thực sự nào cho nó, tôi chỉ muốn biết cách in pi.
DisplayName

@ Amphiteóth Mất khoảng 20 giây để chạy trên máy tính của tôi. Bạn có thể chỉ cần cho nó một chút thời gian.
Paul

2

Phương pháp Monte Carlo

Xem, ví dụ, điều này để giải thích về phương pháp này.

Hãy cẩn thận

  • Không chính xác
  • Mất một thời gian dài để hội tụ bất cứ điều gì hữu ích

Ưu điểm

Vui vẻ :-)

perl -Mbignum -E '
    for(0 .. 1_000_000){
        srand;
        $x=rand; # Random x coordinate
        $y=rand; # Random Y coordinate
        $decision = $x**2 + $y**2 <=1 ? 1:0; # Is this point inside the unit circle?
        $circle += $decision;
        $not_circle += 1-$decision;
        $pi = 4*($circle/($circle+$not_circle)); 
        say $pi
     }'

Lưu ý: Lần đầu tiên tôi đã thử nó mà không srandbị kẹt 3.14và các chữ số sau đó cứ dao động, không bao giờ hội tụ. Điều này có lẽ là vì, sau một thời gian PRNG bắt đầu lặp lại. Việc sử dụng srandsẽ tránh điều đó hoặc ít nhất là kéo dài thời gian của chuỗi giả ngẫu nhiên. Đây chỉ là phỏng đoán, vì vậy hãy sửa tôi nếu tôi sai.


@ Amphiteót Không thực sự chắc chắn những gì đang xảy ra ở đó. Nếu nó giúp Perl của tôi là v5.14.2. Tôi không thực sự thành thạo các bignumhoạt động trong Perl, tôi sợ và tôi không biết bất kỳ phần cụ thể nào của chương trình trên yêu cầu Perl mới hơn. Dù sao, điều thú vị về điều này là chính thuật toán. Hãy thử triển khai nó bằng ngôn ngữ bạn chọn nếu Perl này không phù hợp với bạn.
Joseph R.

1
@ Amphiteót tôi thấy. Liệu chỉnh sửa có giải quyết vấn đề của bạn?
Joseph R.

@ Amphiteót Bạn có thể thử thêm ($x,$y,$circle,$not_circle)=(0,0,0);trước vòng lặp để đảm bảo tất cả các biến được xác định trước khi sử dụng.
Joseph R.

@ Amphiteót Sai lầm của tôi. Các parens ở trên nên có (0,0,0,0).
Joseph R.

Re /5.20.1 này : Có ý nghĩa nhưng không thấy nó! Thật vậy ($x,$y,$circle,$not_circle)=(0,0,0,0). Sau một hoặc hai phút, nó được treo xung quanh giá trị mong muốn, sau đó nó tiến gần hơn đến 3.1409 trước khi tôi dừng lại. Thú vị và vui vẻ! Cảm ơn bạn!

2

Bạn có thể sử dụng thuật toán spigot cho pi. Chương trình C sau đây của Dik Winter và Achim Flammenkamp sẽ tạo ra 15.000 chữ số đầu tiên của pi, mỗi chữ số một chữ số.

a[52514],b,c=52514,d,e,f=1e4,g,h;main(){for(;b=c-=14;h=printf("%04d",e+d/f))for(e=d%=f;g=--b*2;d/=g)d=d*b+f*(h?a[b]:f/5),a[b]=d%--g;}

Bối cảnh: wiki , ở đâyở đây .

1
Tôi yêu thuật toán spigot cho các hằng số logarit của Borwein, Bailey và Plouffe, tuy nhiên, đây không phải là mã golf, vì vậy tôi có thể cải thiện khả năng đọc mã của bạn bằng cách định dạng lại nó không? Cũng lưu ý rằng các thuật toán kiểu BPP chỉ có thể xuất các chữ số cho số pi trong các cơ sở có lũy thừa bằng 2, ít nhất là không sử dụng bộ nhớ bổ sung.
Franki

@Franki định dạng mã thay đổi ý nghĩa hoặc ý định của bài viết? Nếu không, nó sẽ ổn (và chỉnh sửa luôn có thể được khôi phục). Tôi không thấy cách khử mã hóa một số mã có thể làm gì khác hơn là làm rõ.
11684

1
@syntaxerror Đó là sản xuất chính xác 15.000 chữ số trước khi dừng. Đầu ra trong vòng lặp for thứ hai tạo ra 4 chữ số pi và giảm số bí ẩn 52514 bằng 14. Phương trình sau đó sẽ là 4 * (52514/14) bằng 15004. 14 giá trị cuối cùng trong mảng bị bỏ qua tận dụng ít mã thông báo hơn để nhận được giá trị chính xác của chúng tôi là 15000.
Daniel Henneberger

1
@ 11684 Không, nó thực sự sẽ không thay đổi ý nghĩa hoặc ý định của mã. Tuy nhiên, tôi nhận ra đây không phải là thuật toán spigot kiểu BBP cho pi, mà là một thuật toán khác mà người khác đã giải mã ở đây stackoverflow.com/a/25837097
Franki

2

PHP

Một vài ví dụ:

php -r "print pi();"
php -r 'echo M_PI;'
echo "<?=pi();" | php

Nếu bạn muốn thay đổi độ chính xác, hãy thử:

php -d precision=100 -r 'echo pi();'

Kích thước của một float là phụ thuộc vào nền tảng, mặc dù tối đa ~ 1,8e308 với độ chính xác khoảng 14 chữ số thập phân là một giá trị phổ biến (định dạng IEEE 64 bit). [đọc thêm]


Nếu bạn đang tìm kiếm độ chính xác thậm chí chính xác hơn, hãy kiểm tra Rosetta Code hoặc Code Golf SE để biết một số giải pháp lập trình.

Liên quan: Phần mềm có thể tính PI đến ít nhất một nghìn chữ số tại SR.SE


1

Đây là tập lệnh in pi với số chữ số được chỉ định (bao gồm '.') Bởi người dùng.

pi.sh

#!/bin/bash
len=${1:-7}
echo "4*a(1)" | bc -l | cut -c 1-"$len"

đầu ra

$ ./pi.sh 10
3.14159265

và với giá trị mặc định:

$ ./pi.sh
3.14159

Tôi đã thấy mọi người sử dụng scalenhư một bctùy chọn, nhưng trong trường hợp của tôi ( bc 1.06.95) điều này không tạo ra giá trị chính xác:

$ echo "scale=5;4*a(1)" | bc -l
3.14156

Chú ý chữ số cuối cùng.


4
Câu hỏi cho biết: "Tôi muốn chỉ định có bao nhiêu chữ số," trong đó, nói đúng ra là mơ hồ - nhưng tôi nghĩ rằng câu trả lời của bạn không thành công (về mặt kỹ thuật) theo bất kỳ cách giải thích hợp lý nào; ./pi.sh 10in chín chữ số của bạn , đếm số ban đầu 3. Ngoài ra, bạn đang chỉ ngón tay của lỗi làm tròn, nhưng ./pi.sh 6kết quả đầu ra của bạn 3.1415, có thể không tối ưu.
G-Man nói 'Tái lập Monica'

Từ bộ nhớ, scale=Xtùy chọn bcsẽ KHÔNG làm tròn số, mà chỉ cần cắt bỏ số ở chữ số thập phân X-th.
cú pháp

1

Tôi thích câu trả lời của Abey nhưng không thích cách bc thay đổi chữ số cuối cùng.

echo "scale=5; 4*a(1)" | bc -l
3.14156

Vì vậy, tôi loại bỏ quy mô sử dụng printf để đặt số chữ số.

printf "%0.5f\n" $(echo "4*a(1)" | bc -l)
3.14159

Bạn có nhận thấy, sau thang đo 62 chữ số, tất cả đều là 0 trong khi điều này không xảy ra với lệnh ban đầu.

2
@ Amphiteót, Đó là bởi vì printfcó một hạn chế nghiêm trọng về số lượng dấu phẩy động so với bc. Chúng được biểu thị bằng doubleloại ngôn ngữ C với độ chính xác khoảng 17 chữ số, do đó, ngay cả các chữ số khác không sau khoảng 17 chữ số là không có thật! ------ Tôi đã thêm một câu trả lời với làm tròn chính xác kết quả không bị giới hạn bởiprintf . ------ Ngoài ra để đảm bảo rằng lệnh này hoạt động với nhiều địa phương khác nhau, bạn phải làm một cái gì đó như thế này: LC_ALL=C printf...
pabouk

1

Điều gì nếu bạn không thể cho cuộc sống của bạn nhớ điều này arctan? Hoặc giả sử bạn thậm chí không biết chức năng này tồn tại bc, sau đó thử ghi nhớ cách phân chia đơn giản này:

echo "scale=6; 355 / 113" | bc
3.141592

Sẽ chỉ hoạt động cho 6 chữ số, nhưng đối với các tính toán không khoa học, điều này sẽ làm tốt.

Nếu bạn nghĩ rằng bạn không thể nhớ hai số này, hãy viết mẫu số trước, sau đó là tử số:

113 355

Hay tại sao không

11 33 55

"gấp đôi 1, gấp đôi 3, gấp đôi 5". Tất cả các số liệu là số lẻ. Để tính toán, hãy chia một nửa số có 6 chữ số và hoán đổi mẫu số và tử số trước khi chia chúng. Đó là về nó.


Theo như tôi quan tâm, tôi thấy 4 * arctan(1)dễ dàng hơn rất nhiều khi nhớ rằng 2 số có ba chữ số ... Tôi dễ dàng sử dụng 335 thay vì 355 hoặc 133 thay vì 113.
John WH Smith

Chà, tôi nghĩ đó là vấn đề sở thích cá nhân. :) Những người (như tôi), những người có thể dễ dàng ghi nhớ số điện thoại cố định!) Sẽ có thể ghi nhớ hai số chỉ bằng một số điện thoại. Nó cũng sẽ giúp những người ở trường cảm thấy rằng lượng giác phải được tạo ra bởi các thế lực xấu.
cú pháp

1

Có thể giả định rằng OP quan tâm đến lệnh shell ngắn, dễ nhớ để in π - nhưng câu hỏi không thực sự nói lên điều đó. Câu trả lời này là bỏ qua giả định đó và trả lời câu hỏi đúng như được viết;

Không đáng kể?

Mặc dù đã có 18 câu trả lời, một cách tiếp cận vẫn còn thiếu - và với rất nhiều câu trả lời, người ta có thể nghĩ rằng đó không phải là câu trả lời duy nhất còn thiếu:
Cách tiếp cận tầm thường: Làm thế nào để in π? Chỉ cần in π!

Cách tiếp cận đó dường như quá vô dụng để thậm chí không nghĩ về nó, nhưng tôi sẽ chỉ ra rằng nó thực sự có ý nghĩa:

Tối ưu hóa

Chúng ta thường tính giá trị của π. Tôi không thấy những gì ngăn cản chúng tôi tối ưu hóa giải pháp, bằng cách tính toán trước giá trị - đó là một hằng số, bất kỳ trình biên dịch nào cũng sẽ làm điều đó.

Chúng tôi muốn một số chữ số của số pi, lên đến độ chính xác tối đa. Vì vậy, chúng ta chỉ có thể lấy tiền tố của hằng số, dưới dạng văn bản:

echo 3.1415926535897932384626433832795 | cut -b -7
3.14159

Một biến thể với một đối số rõ ràng cho độ chính xác, ví dụ. cho chính xác 5:

echo 3.1415926535897932384626433832795 | cut -b -$((2+5))
3.14159

Ưu điểm

Độ chính xác tối đa có thể được chọn tùy ý bằng cách sử dụng hằng số phù hợp được tính bằng một trong những câu trả lời khác. Nó chỉ bị giới hạn bởi độ dài tối đa của một dòng lệnh.
Nó có độ phức tạp thời gian liên tục để tìm giá trị.
Nó làm cho tất cả các giới hạn và ràng buộc rõ ràng, dựa trên mức độ phức tạp thấp của việc thực hiện.
Nó xử lý độ chính xác lớn hơn mức tối đa một cách duyên dáng bằng cách trả về hằng số trong độ chính xác có sẵn đầy đủ (không có dấu vết 0).
Vì vậy, giải pháp này, trong khi tầm thường, có lợi thế. Nó có thể hữu ích khi nó được sử dụng trong hàm shell chẳng hạn.

Tối thiểu

Chức năng của giải pháp trên cũng có thể được thực hiện mà không cần tạo quy trình cho cut(giả sử echolà một vỏ dựng sẵn). Nó sử dụng lệnh printf(thường là dựng sẵn) theo cách hơi tối nghĩa:
Hằng số được xử lý hoàn toàn dưới dạng một chuỗi (định dạng sử dụng %s), không có arithmethic dấu phẩy động liên quan, do đó các giới hạn floathoặc doublekhông áp dụng ở đây.
Giá trị chính xác của %slối thoát ( 5trong ví dụ bên dưới) chỉ định độ dài của tiền tố chuỗi cần in - đó là độ chính xác. Đây 3.là một phần của printfđịnh dạng để giữ cho nó ra khỏi tính toán chính xác.

$ printf "3.%.5s\n" 1415926535897932384626433832795 
3.14159

Thay thế với độ chính xác như đối số riêng biệt:

$ printf "3.%.*s\n" 5 1415926535897932384626433832795 
3.14159

Hoặc dễ đọc hơn một chút (Lưu ý khoảng trắng giữa 3.14159..., chúng là các đối số riêng biệt):

$ printf "%s%.5s\n" 3. 1415926535897932384626433832795
3.14159

Nhanh

Biến thể sử dụng printfcó thể được dự kiến ​​sẽ rất nhanh: Bởi vì printfmột shell được tích hợp trong các shell thông thường như bashzsh, nó không tạo ra bất kỳ quy trình nào.
Ngoài ra, nó không chạm vào bất kỳ loại mã liên quan đến dấu phẩy động nào, mà chỉ thao tác với các mảng byte (rõ ràng không phải là các ký tự đa dòng). Điều này thường nhanh hơn, thường nhanh hơn nhiều so với việc sử dụng dấu phẩy động.

tương thích printf

Thông thường, có những lý do để thay thế printfbằng /usr/bin/printfđể đảm bảo tính nhất quán hoặc tương thích. Trong trường hợp này, tôi nghĩ rằng chúng ta có thể sử dụng nội dung - điều này rất quan trọng, vì việc sử dụng /usr/bin/printflàm giảm lợi thế "nhanh" bằng cách hủy bỏ một quy trình.
Một vấn đề phổ biến với printfkhả năng tương thích là định dạng đầu ra số tùy thuộc vào miền địa phương. Việc phân tách .các số có thể được thay đổi thành ,dựa trên cài đặt ngôn ngữ; Nhưng chúng tôi không sử dụng số, chỉ là một hằng chuỗi chứa một chữ .- không bị ảnh hưởng bởi miền địa phương.
StéphaneChazelas chỉ ra rằngprintf %.5s hoạt động khác nhau trongzsh, bằng cách đếm các ký tự, không phải byte như bình thường. May mắn thay, các hằng số của chúng tôi chỉ sử dụng các ký tự trong phạm vi ASCII thấp hơn, được mã hóa bởi một byte cho mỗi ký tự trong bất kỳ mã hóa có liên quan nào, miễn là chúng tôi sử dụng UTF-8mã hóa chung cho Unicode và không phải là mã hóa độ rộng cố định.


Lưu ý rằng printf %.5schar (không phải byte) dựa trên zsh (hợp lý, nhưng so với POSIX). ksh93's %.5Lslà dựa trên đồ thị.
Stéphane Chazelas
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.