Derleme zamanında 1 + 2 + 3 +… + 1000'i hesaplamak için C #, C ++ veya Java derleyicisini nasıl çalıştırabilirim?


122

Yakın zamanda yapılan bir röportajda bana gerçekten tuhaf bir soru soruldu. Görüşmeci bana sadece derleyici özelliklerini kullanarak 1 + 2 + 3 + ... + 1000'i nasıl hesaplayabilirim diye sordu. Bu, bir program yazıp çalıştırmama iznim olmadığı anlamına gelir, ancak derleyiciyi derleme sırasında bu toplamı hesaplamaya ve derleme tamamlandığında sonucu yazdırmaya yönlendirebilecek bir program yazmalıyım. Bir ipucu olarak, derleyicinin jeneriklerini ve ön işlemci özelliklerini kullanabileceğimi söyledi. C ++, C # veya Java derleyicisini kullanmak mümkündür. Herhangi bir fikir???

Bu soru, burada sorulan herhangi bir döngü olmadan toplamı hesaplamakla ilgili değildir . Ek olarak, derleme sırasında toplamın hesaplanması GEREKİR. C ++ derleyici yönergelerini kullanarak yalnızca sonucun yazdırılması kabul edilemez.


Gönderilen cevaplar hakkında daha fazla okuduğumda , C ++ şablonlarını kullanarak derleme sırasında problem çözmenin meta programlama olarak adlandırıldığını gördüm . Bu, C ++ dilini standartlaştırma sürecinde Dr. Erwin Unruh tarafından tesadüfen keşfedilen bir tekniktir. Meta programlamanın wiki sayfasında bu konu hakkında daha fazla bilgi edinebilirsiniz . Görünüşe göre programı Java ile java notları kullanarak yazmak mümkün. Aşağıda maress'in cevabına bir göz atabilirsiniz .

C meta programlama ++ ilgili güzel bir kitap bu bir . İlgileniyorsanız bir göz atmaya değer.

Yararlı bir C ++ meta programlama kitaplığı, bu bağlantı Boost'un MPL'sidir .


17
#error "500500" Bir derleme hatası "tamamlanıyor" olarak sayılır mı?
Gizemli

4
İpucu, esasen C ++ şablonlarını kullanmanız anlamına gelir. Açıkçası aynı değil, ancak bu 1'den 1000'e kadar yazdırmak için, eminim bin eklemek için onu değiştirebilirsin ... stackoverflow.com/questions/4568645/…
Joe

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

8
Bazen bazı mülakat sorularının yalnızca mülakat yapanın mülakat yapılana karşı entelektüel üstünlüğünü kanıtlamak için sorulduğunu düşünüyorum.
Chris Dwyer

4
Bir istedin mi para çok bu soru soruldu önce?
Salman A

Yanıtlar:


118

Şimdi iyileştirilmiş özyineleme derinliği ile güncellendi ! MSVC10 ve GCC üzerinde derinliği artırmadan çalışır. :)


Basit derleme zamanı özyineleme + ekleme:

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;
};

deneme kodunda:

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();
}

GCC için çıktı:

hata: 'struct sum_from <1u> :: to <1000u> :: eşittir <500500u>' bildirimi

Ideone'da canlı örnek .

MSVC10 için çıktı:

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

@hsalimi: Yanıtı, işi bitiren bazı kodları gösterecek şekilde düzenledim. :)
Xeo

Vay canına, beni gerçekten etkiledin :-)
Gupta

@hsalimi: Bu tekniği Stockholm'deki 1997 C ++ Standardizasyon toplantısında icat eden Dr. Erwin Unruh'du. Bir dizi asal sayı hesapladı.
Dietmar Kühl

Yineleme olmadan çalışmasını sağlamak için, toplamı hesaplamak için N * (N + 1) / 2 formülünü kullanabilirsiniz.
Adam Gritt

2
@hsalimi C ++ 'da şablon metaprogramlamanın çok daha fantastik örneklerini görmek isterseniz, Andrei Alexandrescu'nun Modern C ++ Tasarımını öneriyorum .
Darhuuk

89

Derleme sırasında hata için C # örneği.

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

Aşağıdaki derleme hatasını üretir:

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

4
@ildjarn C ++ şablon yanıtları ile bunun arasında bir fark var: Bu, şablon isteğe bağlı (?) koda izin verirken burada yalnızca sürekli bölme nedeniyle işe yarıyor. Yine de bir karaktere atamak iyi bir fikir!
Voo

@Voo Evet, ancak adil olmak gerekirse C # bu tür bir programlama için C ++ ile karşılaştırılmaz.
Marlon

3
@Marion Ve ben gerçekten dil tasarımındaki bir hatayı düşünmüyorum;) şablon meta programlamanın tümüyle güçlü olabileceğini, ancak diğer diller yine de tüm bu tuzaklara sahip olmayan diğer çözümlerle çoğu şeyi yapabilir. Derlemesi saatler süren bir proje üzerinde çalışmak zorunda kaldım (tam olarak doğru değil - yinelemeli örnekleme sınırını artırmadıysak inanılmaz derecede hızlıydı .. saniyeler içinde başarısız oldu) ve sürdürmesi korkunçtu. Muhtemelen pek hayran
olmamamın

@Voo: FredOverflow'un yaklaşımı da sürekli katlamaya dayanıyor. Yavaş derlemeye gelince, derleyicinizi suçlayın, dili değil (ipucu - Clang C ++ 'yı hızlı derler ).
ildjarn

@ildjarn Clang son derece karmaşık, gerçekten derinlemesine iç içe geçmiş ve korkunç derecede karmaşık şablonları hızlıca derler? Her şeyin mümkün olduğunu varsayıyorum ve artık test edemiyorum (şükürler olsun) ama hayal edemiyorum. Ayrıca Fred'in burada değil, Xeo'nun yaklaşımından bahsediyorum.
Voo

51

Derleme sırasında derleyicinin bu toplamı hesaplamasını ve derleme tamamlandığında sonucu yazdırmasını sağlayacak bir program yazmalıyım.

Derleme sırasında bir sayı yazdırmanın popüler bir numarası, yazdırmak istediğiniz numara ile somutlaştırılmış bir şablonun var olmayan bir üyesine erişmeye çalışmaktır:

template<int> struct print_n {};

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

Derleyici daha sonra şunu söyler:

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

Bu tekniğin daha ilginç bir örneği için bkz . Derleme zamanında sekiz kraliçe sorununu çözme .


print_nTanımsız kalmasına da izin verebilirsin , cevabımı gör.
Xeo

2
@David Ama Gauss'un zekice bir yola ihtiyacı vardı, aptalca bir hızla bunu yapacak bir bilgisayarı yoktu.
Daniel Fischer

31

Görüşme sorusunda ne derleyici ne de dil belirtilmediğinden, GHC'yi kullanarak Haskell'de bir çözüm sunmaya cesaret ediyorum:

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

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

Derleyin:

$ 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 ...

Ayrıca bir çalışma programımız da var.


20

constexprDerleme zamanı hesaplaması için işlevler ekleyen C ++ 11 ile hayat çok daha kolay olacak , ancak şu anda yalnızca gcc 4.6 veya üstü tarafından destekleniyorlar.

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;

Standart yalnızca derleyicinin 512 özyineleme derinliğini desteklemesini gerektirir, bu nedenle yine de doğrusal özyineleme derinliğinden kaçınması gerekir. İşte çıktı:

$ 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

Elbette şu formülü kullanabilirsiniz:

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, constexprbir an için tamamen unuttum . Belki şablonları çok seviyorum. :(
Xeo

Bu, soruyu ele almak için constexpr'in güzel bir kullanımıdır (bkz. Toplayıcı uygulamasına bakın): kaizer.se/wiki/log/post/C++_constexpr_foldr
Matt

Bu formül taşabilir; son adım, / 2olası unsignedsonuçların tamamını ele almak için , sağa kaydırdığınız değerin n + 1 bit genişliğinde olması gerekir, ancak öyle değil. Bunu önlemek için formülü yeniden düzenlemek mümkündür, clang'ın çalışma zamanı değişken aralıkları için yaptığı gibi: godbolt.org/z/dUGXqg , clang'ın kapalı form formülü bildiğini ve total += idöngüleri optimize etmek için kullandığını gösterir .
Peter Cordes

14

Java'da ek açıklama işlemeyi kullanmayı düşündüm. Apt aracı, kaynak dosyayı javac komutuna gerçekten ayrıştırmadan önce kaynak dosyayı tarar.

Kaynak dosyaların derlenmesi sırasında çıktı şu şekilde yazdırılacaktır:

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

    int offset() default 0;

    int last() default 100;
}

İşlemci fabrikası:

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);
    }
}

Gerçek açıklama işlemcisi:

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)));
            }
        }
    }
}

Ardından bir kaynak dosya oluşturuyoruz. MyInterface ek açıklamasını kullanan basit sınıf:

 @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());
    }
}

Ek açıklama işlemcisi bir jar dosyasına derlenir, ardından apt aracı kaynak dosyayı şu şekilde derlemek için kullanılır:

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

Projenin çıktısı:

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

9

İşte VC ++ 2010 altında çalışan bir uygulama. Şablonlar 500'den fazla kez yinelendiğinde derleyici şikayet ettiğinden hesaplamaları 3 aşamaya ayırmak zorunda kaldım.

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;

Bunu derlediğinizde, bu çıktıyı derleyiciden şu şekilde görmelisiniz:

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>          ]

Parçalamakla çok güzel bir fikir, sanırım bunu bir şekilde cevabıma dahil edeceğim. +1 :)
Xeo

9

Henüz başka kimse olmadığı için bu C kodunu vermek zorunda olduğumu hissediyorum:

#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);
}

Ve tek yapmam gereken, cevabımı bulmak için montajı kontrol etmek!

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

Ve görüyorum:

movl    $500500, -4(%rbp)

C dilinin değil, belirli bir uygulamanın özelliği.
Yavru

5
C'nin "özel uygulaması" olmayan kaç C derleyicisi biliyorsunuz?
Carl Walsh

@Puppy: Genel olsaydı x, derleyicinin ifadeyi derleme zamanında değerlendirmesi (az ya da çok) gerekirdi. ISO C, globaller için çalışma zamanı değişken başlatıcılarına izin vermez. Elbette belirli bir uygulama, onu çalışma zamanında ve depolamalarda hesaplayan yapıcı benzeri bir statik init işlevine bir çağrı gönderebilir. Ancak ISO C, derleme zamanı sabitlerini dizi boyutları olarak kullanmanıza izin verir (örneğin int y[x];, bir yapı tanımında veya başka bir global olarak), bu nedenle herhangi bir varsayımsal karamsar uygulama yine de bunu desteklemelidir.
Peter Cordes

7

Derleme sırasında sonucu gerçekten yazdırmak için Carl Walsh'ın cevabından genişletildi

#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;
}

gcc çıktıları:

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

2

Metaprogramlama yapmak için C ++ makrolarını / şablonlarını kullanabilir (ve çoğunlukla kötüye kullanabilirsiniz) . AFAIK, Java aynı tür şeylere izin vermiyor.


2
Aslında sorunun cevabı değil.
Ikke

Bence haklısın. Java'da, genel bir sınıf parametresi bir değer olamayacağından, bir sınıf olması gerektiğinden, aynı şablon özyineleme numarasını kullanamazsınız.
Eyal Schneider

C # derleyicisinin jenerik özelliği, bazı derleme zamanı hesaplamaları yapmanıza izin verir. Eric Lippert'in bununla ilgili gönderisine bakın .
Allon Guralnek

1

Teorik olarak şunu kullanabilirsiniz:

#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;
}

(Xeo'nun gönderdiği koda göre). Ancak GCC bana şu hatayı veriyor:

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

artı muazzam bir sözde yığın izleme.


Bayrağı kullanmalı: -ftemplate-derinliği-1000
Jetti

@hsalimi: Evet. Ayrıca, bayrağı ekledikten sonra 1000 için de çalışır. Ancak , derleme zamanında basılmıyor ve Xeo, cevabını bu spesifik soruna gerçekten cevap verecek şekilde değiştirdi, bu yüzden cevabımın eski olduğunu düşünüyorum. :-)
ruakh

1

Java kullanarak C # cevabına benzer bir şey yapabilirsiniz:

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;
}

bunu scala'da peano sayıları kullanarak yapabilirsiniz çünkü derleyiciyi özyineleme yapmaya zorlayabilirsiniz, ancak aynı şeyi c # / java'da yapabileceğinizi sanmıyorum

-Xprint kullanmayan ama daha da tehlikeli başka bir çözüm

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

herhangi bir derleyici bayrağı kullanmadan. keyfi sayıda sabiti kontrol edebileceğiniz için (sadece 500500 değil) bu çözüm kabul edilebilir olmalıdır.

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

Üzgünüz , derleyiciyi hesaplamaya yönlendirmediniz 500500 .
Xeo

1
bu üç çözüme de atıfta bulunuyor mu? Çözüm 1'de biraz java kodu aldım ve derledim ve derleyici 500500'ü yazdırdı. Bu, derleyici hesaplama 500500'e çok benziyor. Bu nasıl 500500 hesaplama derleyicisi değil?
benmmurphy

Evet, yeterince doğru, çözüm 2 ve 3'ten bahsediyordum. Bu yanıtı daha önceki bir güncellemede okudum ve en yenisine geri döndüm ve bir şekilde ilk çözümü unutmuşum gibi görünüyor.
Xeo

Çözüm 2 ve 3'ün de hesapladığını söyleyebilirim. temelde yapmakta olduğunuz için rastgele sayıda kontrol ekleyebilirsiniz for (i = 0; i < 100000; ++i) {if (i == 1000*1000/2) print i}. 160 MB'lık bir java dosyam var ve çalışıyor :)
benmmurphy

1

Bu aslında küçük sayılarla çalışsa da, eğer N> 400 olan sum_first kullanıyorsam clang ++ bana bir derleyici hatası veriyor.

#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;
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.