Giúp tôi với phép tính vi phân!


52

Tôi thích lập trình và biết mọi ngôn ngữ, nhưng tôi học toán. Thật không may, trường học của tôi yêu cầu sinh viên máy tính phải mất một năm tính toán. Có một bài kiểm tra vào tuần tới và tôi không biết bất kỳ công thức nào cho các công cụ phái sinh!

Xin hãy giúp tôi tìm các công thức. Tôi cần một bảng cheat - một chương trình (càng ngắn càng tốt để giáo viên của tôi không chú ý đến nó) lấy một biểu thức (như 4*x^3-2) làm đầu vào và xuất ra đạo hàm. (Tôi không quan tâm nếu đầu vào và đầu ra sử dụng các đối số dòng lệnh, STDIN, STDOUT hoặc bất cứ điều gì, vì dù sao tôi cũng đang thực hiện tất cả các phép tính trong đầu.)

Bài kiểm tra bao gồm các loại chức năng sau:

  • Hằng số, thích -3hoặc8.5
  • Các hàm năng lượng, như x^0.5hoặcx^-7
  • Hàm số mũ, như 0.5^xhoặc 7^x(cơ sở luôn dương)
  • Một hằng số nhân với một hàm, như 3*x^5hoặc-0.1*0.3^x
  • Tổng và hiệu của nhiều hàm, như -5*x^2+10-3^x

Giáo viên của tôi luôn định dạng các câu hỏi của mình theo cùng một cách chính xác, như được hiển thị ở trên. Anh ta cũng không sử dụng bất kỳ phân số, số như pi hoặc e hoặc số thực sự lớn (lớn hơn 1.000). Anh ta không bao giờ sử dụng dấu ngoặc đơn và luôn hiển thị phép nhân bằng dấu hoa thị ( *). Biến duy nhất được sử dụng luôn là x .

Mặt khác, giáo viên của tôi khá khoan dung về câu trả lời. Chúng không cần phải được đơn giản hóa hoàn toàn hoặc được định dạng chính xác như được hiển thị ở trên, miễn là nó rõ ràng câu trả lời đang nói gì.

Mặc dù tôi có thể sử dụng bất kỳ ngôn ngữ nào, hãy nhớ rằng tôi không thể tự mình tìm ra các dẫn xuất. Vì vậy, nếu chương trình sử dụng các hàm dựng sẵn để xử lý các phương trình hoặc tính toán các đạo hàm, tôi sẽ không thể sử dụng nó.

Trong quá trình thử nghiệm, tôi sẽ không có quyền truy cập Internet hoặc bất kỳ tệp nào ngoài chương trình trên bảng cheat.

Lưu ý: Kịch bản này là hoàn toàn hư cấu. Trong cuộc sống thực, gian lận và giúp đỡ người khác gian lận là sai và không bao giờ nên làm.


3
Chúng ta có thể mong đợi rằng xluôn luôn là biến để phân biệt?
Kyle Kanos

2
Câu trả lời phải được đơn giản hóa? Chúng ta có cần thêm các điều khoản như?
Rainbolt

1
Tôi đoán đã đến lúc dự án tính toán của tôi tại Scrblnrd3.github.io/Javascript-CAS tỏa sáng nếu tôi thực sự có thể chơi nó
Scrblnrd3

1
Chúng ta có nên cho rằng không có parens?
Không phải Charles

2
Tôi đã trả lời hầu hết các câu hỏi này trong phần chỉnh sửa của mình . Không có ký hiệu khoa học hoặc quy tắc sản phẩm.
Ypnypn

Câu trả lời:


8

Wolfram 136 134 109 [Cảm ơn Calle vì bình luận của anh ấy bên dưới]

Hỗ trợ hạn chế cho các quy tắc sản phẩm và chuỗi.

n=n_?NumberQ;d[v_Plus]:=d/@v;d[v_]:=v/.{x_^n:>x^(n-1)d[x]n,n^x_:>Log[n]d[x]n^x,x_*y__:>d[x]y+d[y]x,n:>0,x:>1}

Thí dụ:

d[3^(x^2)*(x^3+2*x)^2]
>> 2*3^x^2*(2+3*x^2)*(2*x+x^3) + 2*3^x^2*x*(2*x+x^3)^2*Log[3]

Lưu ý rằng điều này không sử dụng bất kỳ "hàm dựng sẵn nào để xử lý các phương trình hoặc tính toán đạo hàm": chỉ liên quan đến khớp mẫu *.

[* Chà ... về mặt kỹ thuật, trình thông dịch cũng phân tích cú pháp và xây dựng một loại AST từ đầu vào]


Ung dung:

d[expr_Plus] := d /@ expr;
d[expr_] := expr /. {
   Power[x_, n_?NumberQ] :> n Power[x, n - 1] d[x],
   Power[n_?NumberQ, x_] :> Log[n] Power[n, x] d[x],
   Times[x_, y__] :> d[x] y + d[y] x,
   n_?NumberQ :> 0,
   x :> 1
}

Đây là một phiên bản khác . Bạn không cần phải viết Power, Timesv.v. IDK sẽ cải thiện bao nhiêu phiên bản chơi gôn của bạn, nhưng bạn có ít nhất một cái Timestrong đó để bạn có thể def. lưu một số nhân vật. Cũng lưu ý rằng trong phiên bản vô danh của bạn, nó nói d[expr_]:= v/....

1
@Calle "IDK bao nhiêu sẽ cải thiện phiên bản chơi gôn của bạn" - 25 byte! Chúc mừng!
Saran

26

Perl - 121 122

(+2 cho -p)

s/(?<![-\d.*^])-?[\d.]+(?![*^\d.])/0/g;s/(?<!\^)x(?!\^)/1/g;s/x\^(-?[\d.]+)/"$1*x^".($1-1)/ge;s/([\d.]+)\^x/ln($1)*$&/g

Kiểm tra:

$ perl -p diff.pl << EOF
> -3
> 8.5
> x^0.5
> x^-7
> 0.5^x
> 7^x
> 3*x^5
> -0.1*0.3^x
> -5*x^2+10-3^x
> EOF
0
0
0.5*x^-0.5
-7*x^-8
ln(0.5)*0.5^x
ln(7)*7^x
3*5*x^4
-0.1*ln(0.3)*0.3^x
-5*2*x^1+0-ln(3)*3^x

Còn một lý do nữa để tôi học regex ...
Kyle Kanos

3
@KyleKanos Đừng. Regex là xấu, regex là tuyệt vời.
mniip

Meh, đánh tôi với nó Không tệ! (PS: regex rất đẹp)
Martin Ender

8
Tôi không biết chuyện gì đang xảy ra ở đây. +1
qwr

4
Giải thích: Hằng số -> 0, x -> 1, x ^ n -> n * x ^ (n-1), a ^ x -> ln (a) * a ^ x
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

7

Haskell 38 Chars

Hàm dlấy một hàm và trả về một hàm. Nó được nhập vào dưới dạng một chuỗi sức mạnh , và được xuất ra theo cùng một cách (đó là một loại của bất cứ điều gì.)

d=zipWith(*)[1..].tail

Ví dụ, nếu chúng ta nhập x->x^2, chúng tôi nhận được x->2*x.

λ <Prelude>: d [0,0,1]
[0,2]

Và cho hàm số mũ.

λ <Prelude>: take 10 exp --exp redefined above to be in power series notation
[1.0,1.0,0.5,0.16666666666666666,4.1666666666666664e-2,8.333333333333333e-3,1.388888888888889e-3,1.984126984126984e-4,2.48015873015873e-5,2.7557319223985893e-6]
λ <Prelude>: let d=zipWith(*)[1..].tail in take 10 $ d exp
[1.0,1.0,0.5,0.16666666666666666,4.1666666666666664e-2,8.333333333333333e-3,1.388888888888889e-3,1.984126984126984e-4,2.48015873015873e-5,2.7557319223985893e-6]

5
Nhưng OP không biết môn toán nào! Chúng ta có thể mong đợi anh ta thể hiện đầu vào theo cấp số nhân của mình như một chuỗi sức mạnh không?
Saran

Vâng, rõ ràng anh ta biết ký hiệu. Anh ta chỉ không biết làm thế nào để thực hiện các hoạt động phái sinh.
PyRulez

5
Điều này có thể xử lý 2^x?
Kyle Kanos

5
Phù thủy này là gì?
Christofer Ohlsson

7
Tôi không thấy nơi nó "lấy một biểu thức (như 4*x^3-2) làm đầu vào", theo yêu cầu của OP.
Gabe

5

Prolog 176

d(N,0):-number(N).
d(x,1).
d(-L,-E):-d(L,E).
d(L+R,E+F):-d(L,E),d(R,F).
d(L-R,E-F):-d(L,E),d(R,F).
d(L*R,E*R+L*F):-d(L,E),d(R,F).
d(L^R,E*R*L^(R-1)+ln(L)*F*L^R):-d(L,E),d(R,F).

Toán tử được hỗ trợ: nhị phân +, nhị phân -, nhị phân *, nhị phân ^, đơn nguyên -. Lưu ý rằng unary +không được hỗ trợ.

Chạy mẫu:

49 ?- d(-3,O).
O = 0.

50 ?- d(8.5,O).
O = 0.

51 ?- d(x^0.5,O).
O = 1*0.5*x^ (0.5-1)+ln(x)*0*x^0.5.

52 ?- d(x^-7,O).
ERROR: Syntax error: Operator expected
ERROR: d(x
ERROR: ** here **
ERROR: ^-7,O) . 
52 ?- d(x^ -7,O).
O = 1* -7*x^ (-7-1)+ln(x)*0*x^ -7.

53 ?- d(x,O).
O = 1.

54 ?- d(0.5^x,O).
O = 0*x*0.5^ (x-1)+ln(0.5)*1*0.5^x.

55 ?- d(7^x,O).
O = 0*x*7^ (x-1)+ln(7)*1*7^x.

56 ?- d(3*x^5,O).
O = 0*x^5+3* (1*5*x^ (5-1)+ln(x)*0*x^5).

57 ?- d(-0.1*0.3^x,O).
O = 0*0.3^x+ -0.1* (0*x*0.3^ (x-1)+ln(0.3)*1*0.3^x).

58 ?- d(-5*x^2+10-3^x,O).
O = 0*x^2+ -5* (1*2*x^ (2-1)+ln(x)*0*x^2)+0- (0*x*3^ (x-1)+ln(3)*1*3^x).

Prolog bối rối khi nó chạy theo ^-trình tự. Một khoảng trắng phải được chèn vào giữa ^-để nó phân tích biểu thức một cách chính xác.

Hy vọng giáo viên của bạn không bận tâm đến sự lộn xộn của phương trình.

Khoảng thời gian điên rồ:

59 ?- d(x^x,O).
O = 1*x*x^ (x-1)+ln(x)*1*x^x.

60 ?- d((x^2-x+1)*4^ -x,O).
O = (1*2*x^ (2-1)+ln(x)*0*x^2-1+0)*4^ -x+ (x^2-x+1)* (0* -x*4^ (-x-1)+ln(4)* - 1*4^ -x).

4

C, 260

Này, tôi nghĩ tôi biết giáo viên của bạn! Không phải là một người có khả năng siêu nhiên để phát hiện học sinh thực hiện các chức năng khớp mẫu thư viện trong đầu sao?

Vì vậy, việc sử dụng sscanflà không cần thiết ... Nhưng đừng lo lắng:

#define P s--||printf(
q=94,s,c,t,a;main(){char i[999],*p=i,*e=p;gets(i);for(;c=*p++,t=q^94|c^45?c%26==16?c%16/3:c/46:1,s=(a="30PCqspP#!C@ #cS` #!cpp#q"[s*5+t])/16-3,a&1&&(p[-1]=0),t||(P"*0"),P"/x"),P"/x*%s",e),P"*ln(%s)",e),s=0),a&2&&(e=p),c;putchar(q=c));}

Chạy các ví dụ (đầu vào trên stdin; đầu ra đi đến stdout):

4 * x ^ 3-2

4*x^3/x*3-2*0

Định dạng này tốt hơn nhiều so với chỉ 12*x^2vì cách này giáo viên của bạn có thể chắc chắn rằng bạn đã tự tính toán câu trả lời và không gian lận bằng cách sao chép nó từ người khác!

x + 2 ^ x

x/x+2^x*ln(2)

Đầu ra có một vấn đề tên miền nhỏ x=0, nhưng nó chính xác ở hầu hết mọi nơi !

Để tham khảo, đây là một phiên bản không được đọc, có thể đọc được (bởi chỉ người phàm). Nó sử dụng một máy trạng thái với 5 trạng thái và 5 loại ký tự đầu vào.

void deriv(char* input)
{
    char* p = input; // current position
    char* exp = p; // base or exponent
    char q = '^'; // previous character

    // State machine has 5 states; here are examples of input:
    // state 0: 123
    // state 1: 123*
    // state 2: 123*x
    // state 3: 123*x^456
    // state 4: 123^x
    int state = 0;

    // Control bits for state machine:
    // bit 0: special action: stop recording base or exponent
    // bit 1: special action: start recording base or exponent
    // bits 4-7: if first column, specify how to calculate the derivative:
    //              3 - multiply the constant term by 0
    //              4 - divide x by x
    //              5 - divide x^n by x and multiply by n
    //              6 - multiply n^x by ln(n)
    // bits 4-7: if not first column, specify the next state
    //              (plus 3, to make the character printable)
    const char* control =
        "\x33\x30\x50\x43\x71"
        "\x73\x70\x50\x23\x21"
        "\x43\x40\x20\x23\x63"
        "\x53\x60\x20\x23\x21"
        "\x63\x70\x70\x23\x71";

    for (;;) {
        int c = *p++;

        // Convert a char to a category:
        // category 0: // - +
        // category 3: // *
        // category 2: // x
        // category 4: // ^
        // category 1: // numbers: 0...9 and decimal point
        int category;
        int action;    

        if (q == '^' && c == '-')
            category = 1; // unary minus is a part of a number
        else
            category = c%26==16?c%16/3:c/46; // just does it

        // Load new state and action to do
        action = control[state * 5 + category];

        if (action & 1)
            p[-1] = 0;
        state = (action >> 4) - 3;
        if (category == 0)
        {
            if (state == 0)
                printf("*0");
            if (state == 1)
                printf("/x");
            if (state == 2)
                printf("/x*%s", exp);
            if (state == 3)
                printf("*ln(%s)", exp);
            state = 0;
        }
        if (action & 2)
            exp = p;

        if (c == 0 || c == '\n') // either of these can mark end of input
            break;

        putchar(c);
        q = c;
    }
}

PS Hãy coi chừng getschức năng đó: nó có một lỗ hổng bảo mật có thể cho phép giáo viên của bạn thực thi rootkit trong tâm trí của bạn bằng cách cung cấp đầu vào quá lâu ...


3

Luân 296 268 263

function d(a)l=""i=a:find"x" if i then if a:sub(i-1,i-1)=="^"then l="log("..a:sub(1,i-2)..")*"..a elseif a:sub(i+1,i+1)=="^"then l=a:sub(i+2).."*"..a:sub(1,i)p=a:sub(i+2)-1 if p~=1 then l= l..a:sub(i+1,i+1)..p end else l=a:sub(1,i-2)end else l="0"end return l end

Không phải là rất golfed và không thể hiện xử lý nhiều thuật ngữ (bạn chỉ có thể chạy nó một vài lần, phải không?), Nhưng nó có thể xử lý n^x, x^nnnhư là đầu vào.


Bị đánh cắp ...

function d(a)
   l=""
   i=a:find"x"
   if i then
      if a:sub(i-1,i-1)=="^" then
         l="log("..a:sub(1,i-2)..")*"..a
      elseif a:sub(i+1,i+1)=="^" then
         l=a:sub(i+2).."*"..a:sub(1,i)
         p=a:sub(i+2)-1 -- this actually does math here
         if p~=1 then
            l= l..a:sub(i+1,i+1)..p
         end
      else
         l=a:sub(1,i-2)
      end
   else
      l="0"
   end
   return l
end

str.func(str,...)== str:func(...), đó là lý do tại sao các chuỗi có thể đạt được sau tất cả ...
mniip

@mniip: Vẫn đang học Lua. Cảm ơn vì tiền hỗ trợ.
Kyle Kanos

1
Vì OP chỉ tìm mã "anh ta có thể tính toán trong đầu", tôi sẽ không bận tâm đến việc xác định hàm và khai báo lcục bộ. Chỉ cần mong đợi đầu vào sẽ được lưu trữ avà nói rằng đầu ra sẽ được lưu trữ trong l.
Martin Ender

Bạn có thể bỏ qua dấu ngoặc đơn a:find("x"), cũng lưu ý rằng 1thenchỉ hoạt động trong Lua 5.2
mniip

@mniip: Whoa, thật tuyệt đó ()là tùy chọn. Điều 1thennày chỉ được sửa vì tôi không có 5.2 (không thực hiện bất kỳ cập nhật CPU nào cho đến khi hoàn thành luận văn b / c Tôi không muốn làm hỏng bất cứ điều gì).
Kyle Kanos

3

ECMAScript 6, 127 byte

Đây là nỗ lực regex của tôi (sử dụng một regex duy nhất và một số logic trong cuộc gọi lại thay thế):

i.replace(/(^|[*+-])(\d+|(?:([\d.]+)\^)?(x)(?:\^(-?[\d.]+))?)(?![.*^])/g,(m,s,a,b,x,e)=>s+(b?'ln'+b+'*'+a:e?e--+'*x^'+e:x?1:0))

Điều này hy vọng chuỗi đầu vào sẽ được lưu trữ ivà chỉ cần trả về kết quả. Dùng thử trong bảng điều khiển tuân thủ ECMAScript 6 (như của Firefox).


2

sed, 110

Theo nghĩa đen "Họ không cần phải đơn giản hóa tất cả hoặc định dạng chính xác như được hiển thị ở trên, miễn là câu trả lời rõ ràng là gì":

s/.*/__&_/;s/x\^(-?[0-9.]+)/\1*x^(\1-1)/g;s/([0-9.]+)\^/ln\1*\1^/g;s/([^(][-+_])[0-9.]+([-+_])/\10\2/g;s/_//g

Số byte bao gồm 1 cho rcờ.

Ungolfed, với ý kiến:

# Add underscores before and after the string, to help with solo-constant recognition
s/.*/__&_/
# Power rule: replace x^c with c*x^(c-1) where c is a number
s/x\^(-?[0-9.]+)/\1*x^(\1-1)/g
# Exponentials: replace c^ with lnc*c^ where c is a number
# (This assumes that there will be an x after the ^)
s/([0-9.]+)\^/ln\1*\1^/g
# Constants: replace ?c? with ?0? where c is a number and ? is +, -, or _
# Except if it's prededed by a parenthesis then don't, because this matches c*x^(c-1)!
s/([^(][-+_])[0-9.]+([-+_])/\10\2/g
# Get rid of the underscores
s/_//g

Chạy mẫu:

$ cat derivatives.txt
-3
8.5
x^0.5
x^-7
0.5^x
7^x
3*x^5
-0.1*0.3^x
-5*x^2+10-3^x

$ sed -re 's/.*/__&_/;s/x\^(-?[0-9.]+)/\1*x^(\1-1)/g;s/([0-9.]+)\^/ln\1*\1^/g;s/([^(][-+_])[0-9.]+([-+_])/\10\2/g;s/_//g' derivatives.txt
-0
0
0.5*x^(0.5-1)
-7*x^(-7-1)
ln0.5*0.5^x
ln7*7^x
3*5*x^(5-1)
-0.1*ln0.3*0.3^x
-5*2*x^(2-1)+0-ln3*3^x

Tôi cá rằng điều này có thể được đánh gôn hơn nữa; đó là lần thử đầu tiên của tôi tại sed. Vui vẻ!


1

Ruby, 152

... hoặc 150 nếu bạn không cần in ... hoặc 147 nếu bạn cũng ổn với một mảng mà bạn cần phải tham gia.

chạy với ruby -nal

p gsub(/(?<!\^)([-+])/,'#\1').split(?#).map{|s|s[/x\^/]?$`+$'+"x^(#{$'}-1)":s[/-?(.*)\^(.*)x/]?s+"*ln(#{$1}*#{$2[0]?$2:1})":s[/\*?x/]?($`[0]?$`:1):p}*''

vô dụng:

p gsub(/(?<!\^)([-+])/,'#\1').split(?#). # insert a # between each additive piece, and then split.
map{ |s|                                 
    if s[/x\^/]                          # if it's c*x^a
        $` + $' + "x^(#{$'}-1)"          #      return c*ax^(a-1)
    elsif s[/-?(.*)\^(.*)x/]             # if it's c*b^(a*x)
        ln = $1 + ?* + ($2[0] ? $2 : 1)  #      return c*b^(a*x)*ln(b*a)
        s+"*ln(#{ln})"
    elsif s[/\*?x/]                      # if it's c*x
        ($`[0] ? $` : 1)                 #      return c
    else                                 # else (constant)
        nil                              #      return nil
    end
}*''

Vấn đề chính của tôi với cái này là số lượng ký tự phân tách thích hợp. Cách khác duy nhất tôi có thể nghĩ là split(/(?<!\^)([-+])/)đưa ra +-như kết quả của riêng họ. Bất kỳ gợi ý cho một giải pháp tốt hơn?

Ngoài ra, có cách nào ngắn hơn để trở lại snếu nó không trống, nhưng nếu không thì quay lại y? Tôi đã sử dụng s[0]?y:s? Trong JS tôi chỉ cần làm s||y, nhưng ""là sự thật trong Ruby.


Một cái nhìn khẳng định sẽ giúp, như vậy : split(/(?<!\^)(?=[-+])/)?
DLosc
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.