Làm cách nào để lái trình biên dịch C #, C ++ hoặc Java để tính toán 1 + 2 + 3 + '+ 1000 khi biên dịch?


122

Trong một cuộc phỏng vấn gần đây, tôi đã được hỏi một câu hỏi thực sự kỳ lạ. Người phỏng vấn hỏi tôi làm thế nào tôi có thể tính 1 + 2 + 3 + ... + 1000 chỉ bằng cách sử dụng các tính năng của trình biên dịch. Điều này có nghĩa là tôi không được phép viết chương trình và thực thi nó, nhưng tôi chỉ nên viết một chương trình có thể điều khiển trình biên dịch để tính tổng này trong khi biên dịch và in kết quả khi quá trình biên dịch hoàn tất. Như một gợi ý, anh ấy nói với tôi rằng tôi có thể sử dụng các tính năng tổng quát và tiền xử lý của trình biên dịch. Có thể sử dụng trình biên dịch C ++, C # hoặc Java. Có ý kiến ​​gì không ???

Câu hỏi này không liên quan đến tính toán tổng mà không có bất kỳ vòng lặp nào được hỏi ở đây . Ngoài ra, cần lưu ý rằng tổng NÊN được tính trong quá trình biên dịch. Chỉ in kết quả bằng chỉ thị trình biên dịch C ++.


Đọc thêm về các câu trả lời được đăng, tôi thấy rằng việc giải quyết các vấn đề trong quá trình biên dịch bằng các mẫu C ++ được gọi là siêu lập trình . Đây là một kỹ thuật được phát hiện tình cờ bởi Tiến sĩ Erwin Unruh, trong quá trình chuẩn hóa ngôn ngữ C ++. Bạn có thể đọc thêm về chủ đề này trên trang wiki về lập trình meta . Dường như có thể viết chương trình bằng Java bằng cách sử dụng các chú thích java. Bạn có thể xem câu trả lời của maress dưới đây.

Một cuốn sách hay về lập trình meta trong C ++ là cuốn này . Đáng để xem nếu quan tâm.

Một thư viện lập trình meta C ++ hữu ích là MPL ​​của Boost liên kết này .


17
#error "500500" Lỗi biên dịch có được tính là "hoàn thành" không?
Bí ẩn

4
Gợi ý về cơ bản có nghĩa là bạn sử dụng các mẫu C ++. Rõ ràng là không giống nhau nhưng cái này là để in từ 1 đến 1000, tôi chắc chắn bạn có thể sửa đổi nó để thêm vào một nghìn ... stackoverflow.com/questions/4568645/ Lỗi
Joe

8
const int value = 1 + 2 + 3.... + 1000; Console.WriteLine(value);; P
George Duckett

8
Đôi khi tôi nghĩ rằng một số câu hỏi phỏng vấn được hỏi chỉ để chứng minh sự vượt trội về trí tuệ của người phỏng vấn so với người được phỏng vấn.
Chris Dwyer

4
Bạn đã yêu cầu rất nhiều tiền trước khi bạn được hỏi câu hỏi này?
Salman A

Câu trả lời:


118

Cập nhật ngay bây giờ với độ sâu đệ quy được cải thiện! Hoạt động trên MSVC10 và GCC mà không tăng độ sâu. :)


Phép đệ quy thời gian biên dịch đơn giản + phép cộng:

template<unsigned Cur, unsigned Goal>
struct adder{
  static unsigned const sub_goal = (Cur + Goal) / 2;
  static unsigned const tmp = adder<Cur, sub_goal>::value;
  static unsigned const value = tmp + adder<sub_goal+1, Goal>::value;
};

template<unsigned Goal>
struct adder<Goal, Goal>{
  static unsigned const value = Goal;
};

Mã kiểm tra:

template<unsigned Start>
struct sum_from{
  template<unsigned Goal>
  struct to{
    template<unsigned N>
    struct equals;

    typedef equals<adder<Start, Goal>::value> result;
  };
};

int main(){
  sum_from<1>::to<1000>::result();
}

Đầu ra cho GCC:

lỗi: khai báo 'struct sum_from <1u> :: đến <1000u> :: bằng <500500u>'

Ví dụ trực tiếp trên Ideone .

Đầu ra cho MSVC10:

error C2514: 'sum_from<Start>::to<Goal>::equals<Result>' : class has no constructors
      with
      [
          Start=1,
          Goal=1000,
          Result=500500
      ]

@hsalimi: Tôi đã chỉnh sửa câu trả lời để thực sự hiển thị một số mã hoàn thành công việc. :)
Xeo

Ồ, bạn thực sự ấn tượng với tôi :-)
Gupta

@hsalimi: Chính Tiến sĩ Erwin Unruh đã phát minh ra kỹ thuật này tại cuộc họp Tiêu chuẩn hóa C ++ năm 1997 tại Stockholm. Ông đã tính toán một loạt các số nguyên tố.
Dietmar Kühl

Để làm cho nó hoạt động mà không cần đệ quy, bạn có thể sử dụng công thức của N * (N + 1) / 2 để tính tổng.
Adam Gritt

2
@hsalimi Trong trường hợp bạn muốn xem nhiều ví dụ tuyệt vời hơn về siêu lập trình mẫu trong C ++, tôi đề xuất Thiết kế C ++ hiện đại của Andrei Alexandrescu.
Darhuuk

89

Ví dụ C # để lỗi tại thời gian biên dịch.

class Foo
{
    const char Sum = (1000 + 1) * 1000 / 2;
}

Tạo ra lỗi biên dịch sau:

Constant value '500500' cannot be converted to a 'char' 

4
@ildjarn Vâng, có một sự khác biệt giữa các câu trả lời của mẫu c ++ và câu trả lời này: Điều này ở đây chỉ hoạt động vì liên tục gập trong khi mẫu cho phép mã tùy ý (?). Vẫn là một ý tưởng tốt để gán nó cho một char!
Voo

@Voo Có, nhưng để công bằng, C # không so sánh với C ++ cho loại lập trình này.
Marlon

3
@Marion Và tôi thực sự không nghĩ rằng một lỗi trong thiết kế ngôn ngữ;) lập trình meta mẫu có thể rất mạnh mẽ, nhưng các ngôn ngữ khác vẫn có thể thực hiện hầu hết mọi thứ với các giải pháp khác không có tất cả những cạm bẫy đó. Tôi đã phải làm việc trong một dự án mất hàng giờ để biên dịch (không hoàn toàn đúng - nó nhanh đến mức không thể tin được nếu chúng tôi không tăng giới hạn tức thời đệ quy .. nó đã thất bại trong vài giây) và thật kinh khủng khi duy trì. Có lẽ là một lý do tại sao tôi không phải là fan hâm mộ của nó ..
Voo

@Voo: Cách tiếp cận của FredOverflow cũng dựa vào việc gấp liên tục. Khi biên dịch chậm, hãy đổ lỗi cho trình biên dịch của bạn chứ không phải ngôn ngữ (gợi ý - Clang biên dịch nhanh C ++ ).
ildjarn

@ildjarn Clang biên dịch các mẫu cực kỳ phức tạp, thực sự sâu sắc và phức tạp nhanh chóng? Tôi cho rằng mọi thứ đều có thể và tôi không thể kiểm tra nó nữa (cảm ơn chúa) nhưng tôi không thể tưởng tượng được. Ngoài ra tôi đang nói về cách tiếp cận của Xeo chứ không phải Fred ở đây.
Voo

51

Tôi chỉ nên viết một chương trình có thể điều khiển trình biên dịch để tính tổng này trong khi biên dịch và in kết quả khi quá trình biên dịch hoàn tất.

Một mẹo phổ biến để in một số trong quá trình biên dịch là cố gắng truy cập vào một thành viên không tồn tại của mẫu được khởi tạo với số bạn muốn in:

template<int> struct print_n {};

print_n<1000 * 1001 / 2>::foobar go;

Trình biên dịch sau đó nói:

error: 'foobar' in 'struct print_n<500500>' does not name a type

Để biết ví dụ thú vị hơn về kỹ thuật này, xem Giải quyết vấn đề tám nữ hoàng tại thời gian biên dịch .


Bạn có thể chỉ cần để print_nkhông xác định, xem câu trả lời của tôi.
Xèo

2
@David Nhưng Gauss cần một cách thông minh, anh ta không có máy tính để làm điều đó một cách ngu ngốc nhanh chóng.
Daniel Fischer

31

Vì cả trình biên dịch lẫn ngôn ngữ đều không được chỉ định trong câu hỏi phỏng vấn, tôi dám gửi giải pháp trong Haskell bằng GHC:

{-# LANGUAGE TemplateHaskell #-}
{-# OPTIONS_GHC -ddump-splices #-}
module Main where

main :: IO ()
main = print $(let x = sum [1 :: Int .. 1000] in [| x |])

Biên dịch nó:

$ ghc compsum.hs
[1 of 1] Compiling Main             ( compsum.hs, compsum.o )
Loading package ghc-prim ... linking ... done.
<snip more "Loading package ..." messages>
Loading package template-haskell ... linking ... done.
compsum.hs:6:16-56: Splicing expression
    let x = sum [1 :: Int .. 1000] in [| x |] ======> 500500
Linking compsum ...

Và chúng tôi cũng có một chương trình làm việc.


20

Cuộc sống sẽ dễ dàng hơn rất nhiều với C ++ 11 có thêm constexprchức năng tính toán thời gian, mặc dù hiện tại chúng chỉ hỗ trợ bởi gcc 4.6 trở lên.

constexpr unsigned sum(unsigned start, unsigned end) {
    return start == end ? start :
        sum(start, (start + end) / 2) +
        sum((start + end) / 2 + 1, end);
}

template <int> struct equals;
equals<sum(1,1000)> x;

Tiêu chuẩn chỉ yêu cầu trình biên dịch hỗ trợ độ sâu đệ quy 512, vì vậy nó vẫn cần tránh độ sâu đệ quy tuyến tính. Đây là đầu ra:

$ g++-mp-4.6 --std=c++0x test.cpp -c
test.cpp:8:25: error: aggregate 'equals<500500> x' has incomplete type and cannot be defined

Tất nhiên bạn chỉ có thể sử dụng công thức:

constexpr unsigned sum(unsigned start, unsigned end) {
    return (start + end) * (end - start + 1) / 2;
}

// static_assert is a C++11 assert, which checks
// at compile time.
static_assert(sum(0,1000) == 500500, "Sum failed for 0 to 1000");

1
+1, hoàn toàn quên mất constexprmột lúc. Có lẽ tôi chỉ thích mẫu quá nhiều. :(
Xeo

Đây là một cách sử dụng tốt của constexpr để giải quyết câu hỏi (xem phần triển khai Adder): kaizer.se/wiki/log/post/C++_constexpr_ Foldr
Matt

Công thức đó có thể tràn; Bước cuối cùng là / 2để xử lý toàn bộ phạm vi unsignedkết quả có thể , giá trị bạn dịch chuyển phải sẽ phải rộng n + 1 bit, nhưng không phải vậy. Bạn có thể sắp xếp lại công thức để tránh điều đó, giống như clang thực hiện cho các phạm vi biến thời gian chạy: godbolt.org/z/dUGXqg cho thấy clang biết công thức dạng đóng và sử dụng nó để tối ưu hóa total += icác vòng lặp.
Peter Cordes

14

Trong java, tôi nghĩ về việc sử dụng xử lý chú thích. Công cụ apt quét tệp nguồn trước khi thực sự phân tích tệp nguồn thành lệnh javac.

Trong quá trình biên dịch các tệp nguồn, đầu ra sẽ được in ra:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface MyInterface {

    int offset() default 0;

    int last() default 100;
}

Nhà máy xử lý:

public class MyInterfaceAnnotationProcessorFactory implements AnnotationProcessorFactory {

    public Collection<String> supportedOptions() {
        System.err.println("Called supportedOptions.............................");
        return Collections.EMPTY_LIST;
    }

    public Collection<String> supportedAnnotationTypes() {
        System.err.println("Called supportedAnnotationTypes...........................");
        return Collections.singletonList("practiceproject.MyInterface");
    }

    public AnnotationProcessor getProcessorFor(Set<AnnotationTypeDeclaration> set, AnnotationProcessorEnvironment ape) {
        System.err.println("Called getProcessorFor................");
        if (set.isEmpty()) {
            return AnnotationProcessors.NO_OP;
        }
        return new MyInterfaceAnnotationProcessor(ape);
    }
}

Bộ xử lý chú thích thực tế:

public class MyInterfaceAnnotationProcessor implements AnnotationProcessor {

    private AnnotationProcessorEnvironment ape;
    private AnnotationTypeDeclaration atd;

    public MyInterfaceAnnotationProcessor(AnnotationProcessorEnvironment ape) {
        this.ape = ape;
        atd = (AnnotationTypeDeclaration) ape.getTypeDeclaration("practiceproject.MyInterface");
    }

    public void process() {
        Collection<Declaration> decls = ape.getDeclarationsAnnotatedWith(atd);
        for (Declaration dec : decls) {
            processDeclaration(dec);
        }
    }

    private void processDeclaration(Declaration d) {
        Collection<AnnotationMirror> ams = d.getAnnotationMirrors();
        for (AnnotationMirror am : ams) {
            if (am.getAnnotationType().getDeclaration().equals(atd)) {
                Map<AnnotationTypeElementDeclaration, AnnotationValue> values = am.getElementValues();
                int offset = 0;
                int last = 100;
                for (Map.Entry<AnnotationTypeElementDeclaration, AnnotationValue> entry : values.entrySet()) {
                    AnnotationTypeElementDeclaration ated = entry.getKey();
                    AnnotationValue v = entry.getValue();
                    String name = ated.getSimpleName();
                    if (name.equals("offset")) {
                        offset = ((Integer) v.getValue()).intValue();
                    } else if (name.equals("last")) {
                        last = ((Integer) v.getValue()).intValue();
                    }
                }
                //find the sum
                System.err.println("Sum: " + ((last + 1 - offset) / 2) * (2 * offset + (last - offset)));
            }
        }
    }
}

Sau đó, chúng tôi tạo ra một tập tin nguồn. lớp đơn giản sử dụng chú thích MyInterface:

 @MyInterface(offset = 1, last = 1000)
public class Main {

    @MyInterface
    void doNothing() {
        System.out.println("Doing nothing");
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        Main m = new Main();
        m.doNothing();
        MyInterface my = (MyInterface) m.getClass().getAnnotation(MyInterface.class);
        System.out.println("offset: " + my.offset());
        System.out.println("Last: " + my.last());
    }
}

Bộ xử lý chú thích được biên dịch thành tệp jar, sau đó công cụ apt được sử dụng để biên dịch tệp nguồn dưới dạng:

apt -cp "D:\Variance project\PracticeProject\dist\practiceproject.jar" -factory practiceproject.annotprocess.MyInterfaceAnnotationProcessorFactory "D:\Variance project\PracticeProject2\src\practiceproject2\Main.java"

Đầu ra của dự án:

Called supportedAnnotationTypes...........................
Called getProcessorFor................
Sum: 5000
Sum: 500500

9

Đây là một triển khai hoạt động theo VC ++ 2010. Tôi đã phải chia các tính toán thành 3 giai đoạn kể từ khi trình biên dịch phàn nàn khi các mẫu đệ quy hơn 500 lần.

template<int t_startVal, int t_baseVal = 0, int t_result = 0>
struct SumT
{
    enum { result = SumT<t_startVal - 1, t_baseVal, t_baseVal + t_result +
        t_startVal>::result };
};

template<int t_baseVal, int t_result>
struct SumT<0, t_baseVal, t_result>
{
    enum { result = t_result };
};

template<int output_value>
struct Dump
{
    enum { value = output_value };
    int bad_array[0];
};

enum
{
    value1 = SumT<400>::result,                // [1,400]
    value2 = SumT<400, 400, value1>::result,   // [401, 800]
    value3 = SumT<200, 800, value2>::result    // [801, 1000]
};

Dump<value3> dump;

Khi bạn biên dịch cái này, bạn sẽ thấy đầu ra này từ trình biên dịch giống như thế này:

1>warning C4200: nonstandard extension used : zero-sized array in struct/union
1>          Cannot generate copy-ctor or copy-assignment operator when UDT contains a 
zero-sized array
1>          templatedrivensum.cpp(33) : see reference to class template 
instantiation 'Dump<output_value>' being compiled
1>          with
1>          [
1>              output_value=500500
1>          ]

Ý tưởng rất hay với việc phá vỡ nó, tôi nghĩ rằng tôi sẽ kết hợp nó vào câu trả lời của mình bằng cách nào đó. +1 :)
Xeo

9

Tôi cảm thấy bắt buộc phải cung cấp mã C này, vì chưa có ai khác:

#include <stdio.h>
int main() {
   int x = 1+2+3+4+5+6+7+8+9+10+11+12+13+14+15+16+17+18+19+20+
           21+22+23+24+25+26+27+28+29+30+31+32+33+34+35+36+37+38+39+40+
           41+42+43+44+45+46+47+48+49+50+51+52+53+54+55+56+57+58+59+60+
           61+62+63+64+65+66+67+68+69+70+71+72+73+74+75+76+77+78+79+80+
           81+82+83+84+85+86+87+88+89+90+91+92+93+94+95+96+97+98+99+100+     
           101+102+103+104+105+106+107+108+109+110+111+112+113+114+115+116+117+118+119+120+
           121+122+123+124+125+126+127+128+129+130+131+132+133+134+135+136+137+138+139+140+
           141+142+143+144+145+146+147+148+149+150+151+152+153+154+155+156+157+158+159+160+
           161+162+163+164+165+166+167+168+169+170+171+172+173+174+175+176+177+178+179+180+
           181+182+183+184+185+186+187+188+189+190+191+192+193+194+195+196+197+198+199+200+
           201+202+203+204+205+206+207+208+209+210+211+212+213+214+215+216+217+218+219+220+
           221+222+223+224+225+226+227+228+229+230+231+232+233+234+235+236+237+238+239+240+
           241+242+243+244+245+246+247+248+249+250+251+252+253+254+255+256+257+258+259+260+
           261+262+263+264+265+266+267+268+269+270+271+272+273+274+275+276+277+278+279+280+
           281+282+283+284+285+286+287+288+289+290+291+292+293+294+295+296+297+298+299+300+
           301+302+303+304+305+306+307+308+309+310+311+312+313+314+315+316+317+318+319+320+
           321+322+323+324+325+326+327+328+329+330+331+332+333+334+335+336+337+338+339+340+
           341+342+343+344+345+346+347+348+349+350+351+352+353+354+355+356+357+358+359+360+
           361+362+363+364+365+366+367+368+369+370+371+372+373+374+375+376+377+378+379+380+
           381+382+383+384+385+386+387+388+389+390+391+392+393+394+395+396+397+398+399+400+
           401+402+403+404+405+406+407+408+409+410+411+412+413+414+415+416+417+418+419+420+
           421+422+423+424+425+426+427+428+429+430+431+432+433+434+435+436+437+438+439+440+
           441+442+443+444+445+446+447+448+449+450+451+452+453+454+455+456+457+458+459+460+
           461+462+463+464+465+466+467+468+469+470+471+472+473+474+475+476+477+478+479+480+
           481+482+483+484+485+486+487+488+489+490+491+492+493+494+495+496+497+498+499+500+
           501+502+503+504+505+506+507+508+509+510+511+512+513+514+515+516+517+518+519+520+
           521+522+523+524+525+526+527+528+529+530+531+532+533+534+535+536+537+538+539+540+
           541+542+543+544+545+546+547+548+549+550+551+552+553+554+555+556+557+558+559+560+
           561+562+563+564+565+566+567+568+569+570+571+572+573+574+575+576+577+578+579+580+
           581+582+583+584+585+586+587+588+589+590+591+592+593+594+595+596+597+598+599+600+
           601+602+603+604+605+606+607+608+609+610+611+612+613+614+615+616+617+618+619+620+
           621+622+623+624+625+626+627+628+629+630+631+632+633+634+635+636+637+638+639+640+
           641+642+643+644+645+646+647+648+649+650+651+652+653+654+655+656+657+658+659+660+
           661+662+663+664+665+666+667+668+669+670+671+672+673+674+675+676+677+678+679+680+
           681+682+683+684+685+686+687+688+689+690+691+692+693+694+695+696+697+698+699+700+
           701+702+703+704+705+706+707+708+709+710+711+712+713+714+715+716+717+718+719+720+
           721+722+723+724+725+726+727+728+729+730+731+732+733+734+735+736+737+738+739+740+
           741+742+743+744+745+746+747+748+749+750+751+752+753+754+755+756+757+758+759+760+
           761+762+763+764+765+766+767+768+769+770+771+772+773+774+775+776+777+778+779+780+
           781+782+783+784+785+786+787+788+789+790+791+792+793+794+795+796+797+798+799+800+
           801+802+803+804+805+806+807+808+809+810+811+812+813+814+815+816+817+818+819+820+
           821+822+823+824+825+826+827+828+829+830+831+832+833+834+835+836+837+838+839+840+
           841+842+843+844+845+846+847+848+849+850+851+852+853+854+855+856+857+858+859+860+
           861+862+863+864+865+866+867+868+869+870+871+872+873+874+875+876+877+878+879+880+
           881+882+883+884+885+886+887+888+889+890+891+892+893+894+895+896+897+898+899+900+
           901+902+903+904+905+906+907+908+909+910+911+912+913+914+915+916+917+918+919+920+
           921+922+923+924+925+926+927+928+929+930+931+932+933+934+935+936+937+938+939+940+
           941+942+943+944+945+946+947+948+949+950+951+952+953+954+955+956+957+958+959+960+
           961+962+963+964+965+966+967+968+969+970+971+972+973+974+975+976+977+978+979+980+
           981+982+983+984+985+986+987+988+989+990+991+992+993+994+995+996+997+998+999+1000;
  printf("%d\n", x);
}

Và tất cả những gì tôi cần làm là kiểm tra lắp ráp để tìm câu trả lời của tôi!

gcc -S compile_sum.c;
grep "\$[0-9]*, *-4" compile_sum.s

Và tôi thấy:

movl    $500500, -4(%rbp)

Tính năng của một thực hiện cụ thể, không phải ngôn ngữ C.
Cún con

5
Có bao nhiêu trình biên dịch C mà bạn biết đó không phải là "triển khai cụ thể" của C?
Carl Walsh

@Puppy: Nếu xlà toàn cục, trình biên dịch sẽ được yêu cầu (nhiều hơn hoặc ít hơn) để đánh giá biểu thức tại thời điểm biên dịch. ISO C không cho phép khởi tạo biến thời gian chạy cho toàn cục. Tất nhiên, một triển khai cụ thể có thể phát ra một cuộc gọi đến hàm khởi tạo tĩnh giống như hàm tạo để tính toán nó trong thời gian chạy và lưu trữ. Nhưng ISO C không cho phép bạn sử dụng các hằng số thời gian biên dịch dưới dạng kích thước mảng (ví dụ như int y[x];trong định nghĩa cấu trúc hoặc như một toàn cầu khác), do đó, bất kỳ triển khai bi quan giả định nào vẫn sẽ phải hỗ trợ điều đó.
Peter Cordes

7

Mở rộng từ câu trả lời của Carl Walsh để thực sự in kết quả trong quá trình biên dịch:

#define VALUE (1+2+3+4+5+6+7+8+9+10+11+12+13+14+15+16+17+18+19+20+\
21+22+23+24+25+26+27+28+29+30+31+32+33+34+35+36+37+38+39+40+\
41+42+43+44+45+46+47+48+49+50+51+52+53+54+55+56+57+58+59+60+\
61+62+63+64+65+66+67+68+69+70+71+72+73+74+75+76+77+78+79+80+\
81+82+83+84+85+86+87+88+89+90+91+92+93+94+95+96+97+98+99+100+\
101+102+103+104+105+106+107+108+109+110+111+112+113+114+115+116+117+118+119+120+\
121+122+123+124+125+126+127+128+129+130+131+132+133+134+135+136+137+138+139+140+\
141+142+143+144+145+146+147+148+149+150+151+152+153+154+155+156+157+158+159+160+\
161+162+163+164+165+166+167+168+169+170+171+172+173+174+175+176+177+178+179+180+\
181+182+183+184+185+186+187+188+189+190+191+192+193+194+195+196+197+198+199+200+\
201+202+203+204+205+206+207+208+209+210+211+212+213+214+215+216+217+218+219+220+\
221+222+223+224+225+226+227+228+229+230+231+232+233+234+235+236+237+238+239+240+\
241+242+243+244+245+246+247+248+249+250+251+252+253+254+255+256+257+258+259+260+\
261+262+263+264+265+266+267+268+269+270+271+272+273+274+275+276+277+278+279+280+\
281+282+283+284+285+286+287+288+289+290+291+292+293+294+295+296+297+298+299+300+\
301+302+303+304+305+306+307+308+309+310+311+312+313+314+315+316+317+318+319+320+\
321+322+323+324+325+326+327+328+329+330+331+332+333+334+335+336+337+338+339+340+\
341+342+343+344+345+346+347+348+349+350+351+352+353+354+355+356+357+358+359+360+\
361+362+363+364+365+366+367+368+369+370+371+372+373+374+375+376+377+378+379+380+\
381+382+383+384+385+386+387+388+389+390+391+392+393+394+395+396+397+398+399+400+\
401+402+403+404+405+406+407+408+409+410+411+412+413+414+415+416+417+418+419+420+\
421+422+423+424+425+426+427+428+429+430+431+432+433+434+435+436+437+438+439+440+\
441+442+443+444+445+446+447+448+449+450+451+452+453+454+455+456+457+458+459+460+\
461+462+463+464+465+466+467+468+469+470+471+472+473+474+475+476+477+478+479+480+\
481+482+483+484+485+486+487+488+489+490+491+492+493+494+495+496+497+498+499+500+\
501+502+503+504+505+506+507+508+509+510+511+512+513+514+515+516+517+518+519+520+\
521+522+523+524+525+526+527+528+529+530+531+532+533+534+535+536+537+538+539+540+\
541+542+543+544+545+546+547+548+549+550+551+552+553+554+555+556+557+558+559+560+\
561+562+563+564+565+566+567+568+569+570+571+572+573+574+575+576+577+578+579+580+\
581+582+583+584+585+586+587+588+589+590+591+592+593+594+595+596+597+598+599+600+\
601+602+603+604+605+606+607+608+609+610+611+612+613+614+615+616+617+618+619+620+\
621+622+623+624+625+626+627+628+629+630+631+632+633+634+635+636+637+638+639+640+\
641+642+643+644+645+646+647+648+649+650+651+652+653+654+655+656+657+658+659+660+\
661+662+663+664+665+666+667+668+669+670+671+672+673+674+675+676+677+678+679+680+\
681+682+683+684+685+686+687+688+689+690+691+692+693+694+695+696+697+698+699+700+\
701+702+703+704+705+706+707+708+709+710+711+712+713+714+715+716+717+718+719+720+\
721+722+723+724+725+726+727+728+729+730+731+732+733+734+735+736+737+738+739+740+\
741+742+743+744+745+746+747+748+749+750+751+752+753+754+755+756+757+758+759+760+\
761+762+763+764+765+766+767+768+769+770+771+772+773+774+775+776+777+778+779+780+\
781+782+783+784+785+786+787+788+789+790+791+792+793+794+795+796+797+798+799+800+\
801+802+803+804+805+806+807+808+809+810+811+812+813+814+815+816+817+818+819+820+\
821+822+823+824+825+826+827+828+829+830+831+832+833+834+835+836+837+838+839+840+\
841+842+843+844+845+846+847+848+849+850+851+852+853+854+855+856+857+858+859+860+\
861+862+863+864+865+866+867+868+869+870+871+872+873+874+875+876+877+878+879+880+\
881+882+883+884+885+886+887+888+889+890+891+892+893+894+895+896+897+898+899+900+\
901+902+903+904+905+906+907+908+909+910+911+912+913+914+915+916+917+918+919+920+\
921+922+923+924+925+926+927+928+929+930+931+932+933+934+935+936+937+938+939+940+\
941+942+943+944+945+946+947+948+949+950+951+952+953+954+955+956+957+958+959+960+\
961+962+963+964+965+966+967+968+969+970+971+972+973+974+975+976+977+978+979+980+\
981+982+983+984+985+986+987+988+989+990+991+992+993+994+995+996+997+998+999+1000)

char tab[VALUE];

int main()
{
    tab = 5;
}

đầu ra gcc:

test.c: In function 'main':
test.c:56:9: error: incompatible types when assigning to type 'char[500500]' fro
m type 'int'

2

Bạn có thể sử dụng (và chủ yếu là lạm dụng) các macro / mẫu C ++ để thực hiện siêu lập trình . AFAIK, Java không cho phép điều tương tự.


2
Không thực sự là một câu trả lời cho câu hỏi.
Ikke

Tôi nghĩ bạn đúng. Trong java, bạn không thể sử dụng cùng một thủ thuật đệ quy mẫu, vì một tham số lớp chung không thể là một giá trị - nó phải là một lớp.
Eyal Schneider

Tính năng tổng quát của trình biên dịch C # cho phép bạn thực hiện một số tính toán thời gian biên dịch. Xem bài của Eric Lippert về điều này.
Allon Guralnek

1

Về lý thuyết, bạn có thể sử dụng điều này:

#include <iostream>

template<int N>
struct Triangle{
  static int getVal()
  {
    return N + Triangle<N-1>::getVal();
  }
};

template<>
struct Triangle<1>{
  static int getVal()
  {
    return 1;
  }
};

int main(){
   std::cout << Triangle<1000>::getVal() << std::endl;
   return 0;
}

(dựa trên mã mà Xeo đăng). Nhưng GCC cho tôi lỗi này:

triangle.c++:7: error: template instantiation depth exceeds maximum of 500 (use -ftemplate-depth-NN to increase the maximum) instantiating struct Triangle<500>

cộng với một chồng giả khổng lồ.


Phải sử dụng cờ: -ftemplate-height-1000
Jetti

@hsalimi: Vâng. Nó cũng hoạt động cho 1000, khi bạn thêm cờ. Nhưng nó không được in vào thời gian biên dịch và Xeo đã thay đổi câu trả lời của anh ấy / cô ấy để thực sự trả lời vấn đề cụ thể này, vì vậy tôi nghĩ rằng câu trả lời của tôi đã lỗi thời. :-)
ruakh

1

Sử dụng java, bạn có thể làm điều tương tự với câu trả lời C #:

public class Cheat {
    public static final int x = (1000 *1001/2);
}

javac -Xprint Cheat.java

public class Cheat {

  public Cheat();
  public static final int x = 500500;
}

bạn có thể làm điều này trong scala bằng cách sử dụng số peano vì bạn có thể buộc trình biên dịch thực hiện đệ quy nhưng tôi không nghĩ bạn có thể làm điều tương tự trong c # / java

một giải pháp khác không sử dụng -Xprint mà thậm chí còn tinh ranh hơn

public class Cheat {
  public static final int x = 5/(1000 *1001/2 - 500500);
}

javac -Xlint:all Cheat.java

Cheat.java:2: warning: [divzero] division by zero
  public static final int x = 5/(1000 *1001/2 - 500500);
                            ^
1 warning

mà không sử dụng bất kỳ cờ biên dịch. vì bạn có thể kiểm tra số lượng hằng số tùy ý (không chỉ 500500), giải pháp này có thể được chấp nhận.

public class Cheat {
  public static final short max = (Short.MAX_VALUE - 500500) + 1001*1000/2;
  public static final short overflow = (Short.MAX_VALUE - 500500 + 1) + 1001*1000/2;

}

Cheat.java:3: error: possible loss of precision
  public static final short overflow = (Short.MAX_VALUE - 500500 + 1) + 1001*1000/2;
                                                                  ^
  required: short
  found:    int
1 error

Bạn đã không lái trình biên dịch để tính toán 500500 , xin lỗi.
Xèo

1
điều này có liên quan đến cả ba giải pháp không? trong giải pháp 1 tôi đã lấy một số mã java và biên dịch nó và trình biên dịch đã in ra 500500. trông rất giống trình biên dịch tính toán 500500. làm thế nào đây không phải là trình biên dịch tính toán 500500?
benmmurphy

Vâng, đúng như vậy, tôi đã nói về giải pháp 2 và 3. Tôi đã đọc câu trả lời này trên một bản cập nhật trước đó và quay lại bản mới nhất và dường như đã quên mất giải pháp đầu tiên.
Xèo

tôi muốn nói rằng giải pháp 2 & 3 cũng đang tính toán nó. bạn có thể thêm một số kiểm tra tùy ý để cơ bản bạn đang làm for (i = 0; i < 100000; ++i) {if (i == 1000*1000/2) print i}. Tôi có một tệp java
160mb

1

Mặc dù điều này thực sự hoạt động với số lượng nhỏ, clang ++ trả lại cho tôi lỗi trình biên dịch nếu tôi đang sử dụng sum_first trong đó N> 400.

#include <iostream>

using namespace std;


template <int N>
struct sum_first
{
   static const int value = N + sum_first<N - 1>::value;
};

template <>
struct sum_first<0>
{
    static const int value = 0;
};

int main()
{
    cout << sum_first<1000>::value << endl;
}
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.