Здравствуйте, Hard_Club, Вы писали:
H_C>переносим свой Python код на C++. У нас там был в H_C>Python конфиг в котором константами задавалось (было порядка 30 параметров):
H_C>CPU_NUM = getenv("CPU_NUM", 3) # default
H_C>если ли в C++ какой-то рекомендуемый способ/либа для конфигов?
яд бы не заморачивался. если надо getenv сделайте себе getenv
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
int getenv(const char* name,int defval) {
long int val; char *end, *text=getenv(name);
if (!text) return defval;
val=strtol(text,&end,10);
if (val==0 && errno) return defval;
if (*end) return defval;
if ((int)val!=val) return defval;
return val;
}
Здравствуйте, kov_serg, Вы писали:
_>яд бы не заморачивался. если надо getenv сделайте себе getenv _>
_>#include <stdio.h>
_>#include <errno.h>
_>#include <stdlib.h>
_>int getenv(const char* name,int defval) {
_> long int val; char *end, *text=getenv(name);
_> if (!text) return defval;
_> val=strtol(text,&end,10);
_> if (val==0 && errno) return defval;
_> if (*end) return defval;
_> if ((int)val!=val) return defval;
_> return val;
_>}
_>
В функции прикопан баг, который когда-нибудь бахнет.(Я подрывался) strtol выставит errno при ошибке, но не сбросит его при успехе. Если errno уже выставлен кем-то ранее, то вместо 0 будет возвращаться defval.
Здравствуйте, vadfromnu, Вы писали:
V>В функции прикопан баг, который когда-нибудь бахнет.(Я подрывался) strtol выставит errno при ошибке, но не сбросит его при успехе. Если errno уже выставлен кем-то ранее, то вместо 0 будет возвращаться defval.
Здравствуйте, kov_serg, Вы писали: _>Здравствуйте, vadfromnu, Вы писали: V>>В функции прикопан баг, который когда-нибудь бахнет.(Я подрывался) strtol выставит errno при ошибке, но не сбросит его при успехе. Если errno уже выставлен кем-то ранее, то вместо 0 будет возвращаться defval. _>Действительно https://github.com/gcc-mirror/gcc/blob/master/libiberty/strtol.c _>Тогда так:
Сорян, что не по теме, но это выглядит, как говнокод. Строчки экономишь?
ЗЫ Моя версия, не факт, что рабочая — просто по-человечески переписал даденое. Да, в три раза длиннее получилось, если считать по строчкам
Скрытый текст
#include <stdlib.h>
struct int_parsing_traits
{
// Методы не упаковываем в одну строчку (хотя они очень просятся) чтобы можно было
// остановится в отладчике и посмотреть одновременно на входной параметр, и на условиеbool is_space(char c) const
{
return c>0 && c<=32;
}
bool is_digit(char c) const
{
return c>='0' && c<='9';
}
bool is_sign(char c) const
{
return c=='-' || c=='+';
}
bool is_negate_sign(char c) const
{
return c=='-';
}
int to_digit(char c) const
{
return (c>='0' && c<='9') ? c-'0' : -1;
}
// Решили, что системой счисления управляет ParsingTraitsunsigned get_base() const
{
return 10;
}
}; // struct int_parsing_traitstemplate<typename ParsingTraits>
inline
int getint( const char *p, int defval = 0, const ParsingTraits &parsingTraits = int_parsing_traits() )
{
// skip leading whitespaceswhile( *p && parsingTraits.is_space(*p) )
p++;
// check for leading signif (!parsingTraits.is_sign(*p))
return defval;
bool neg = false;
// is negative number?if (parsingTraits.is_negate_sign(*p))
neg = true;
unsigned resultAbs = 0;
while(*p && parsingTraits.is_digit(*p))
{
int digit = parsingTraits.to_digit();
// Тут можно вставить проверку на систему счисления,
// а можно положится, что ParsingTraits сама знает, что делаетif (digit<0)
break;
// А тут мы уже точно решили, что ParsingTraits знает систему счисленияunsigned newRes = resultAbs * parsingTraits.get_base() + (unsigned)digit;
if (newRes<resultAbs)
return defval; // переполнились
resultAbs = newRes;
p++;
}
// Пробегаем по оставшейся строке, надеясь, что она состоит из пробеловwhile(*p && parsingTraits.is_space(*p))
++p;
if ( *p && !parsingTraits.is_space(*p) )
return defval; // стопанули на чём-то, не похожем на цифру или пробелint result = (int)resultAbs;
if (neg)
result = -result;
if (unsigned(result)!=resultAbs)
return defval; // переполнение при смене знакаreturn result;
}
Здравствуйте, Marty, Вы писали:
M>Сорян, что не по теме, но это выглядит, как говнокод. Строчки экономишь?
Если оно крякает как утака, и плавает как утка — возможно это и есть утка.
Я придерживался правила что демонстрационный код, должен умещаться на одном экране, его должно быть легко объяснить на пальцах.
Каждая строчка выполняет какое-то одно осмысленное действие. То что в С++ для отдельных осмысленных операций приходится писать много букв это издержки конкретного языка. Да и использование итератора строки с разными типами символов, экзотических кодировок и чудных систем исчисления типа 36#2QJBZ и другие гибкости в данном конкретном случае были бы излишними.
Здравствуйте, Marty, Вы писали:
M>Плохая идея. Как обеспечить конфигурирование нескольких экземпляров приложения?
# CPU_NUM=32 ./app &
# CPU_NUM=16 ./app &
M>Из переменых окружения имхо стоит брать только переопределения зашитых дефолтных значений, не более того
Ситуации бывают разные: зачем сразу ломать обратную совместимость?
Здравствуйте, kov_serg, Вы писали:
M>>Сорян, что не по теме, но это выглядит, как говнокод. Строчки экономишь? _>Если оно крякает как утака, и плавает как утка — возможно это и есть утка.
Ты наверное хотел сказать: "Если оно пачкает как говно, и плавает как говно — возможно это и есть говно"?
_>Я придерживался правила что демонстрационный код, должен умещаться на одном экране, его должно быть легко объяснить на пальцах.
Странное правило. Демонстрационный код должен быть понятен, это основное требование к нему.
Твой код выглядит так, как-будто вытащен из говнопроекта. И да, на пальцах там ничего не объяснить.
_>Каждая строчка выполняет какое-то одно осмысленное действие.
Не одно, а кучу.
_>То что в С++ для отдельных осмысленных операций приходится писать много букв это издержки конкретного языка.
Это не так. Ты просто видимо привык, что какой-то узкий спектр твоих задач хорошо покрывается средствами используемого тобой языка. Тебе повезло, что твой язык хорошо подходит под твои задачи
_>Да и использование итератора строки с разными типами символов, экзотических кодировок и чудных систем исчисления типа 36#2QJBZ и другие гибкости в данном конкретном случае были бы излишними.
M>>Плохая идея. Как обеспечить конфигурирование нескольких экземпляров приложения? _># CPU_NUM=32 ./app & _># CPU_NUM=16 ./app &
Непортируемо.
M>>Из переменых окружения имхо стоит брать только переопределения зашитых дефолтных значений, не более того _>Ситуации бывают разные: зачем сразу ломать обратную совместимость?
Здравствуйте, Marty, Вы писали:
M>Ты наверное хотел сказать: "Если оно пачкает как говно, и плавает как говно — возможно это и есть говно"?
Не нравиться не ешь. Я нигде не говорил что я являюсь образцом для подражания.
M>Странное правило. Демонстрационный код должен быть понятен, это основное требование к нему. M>Твой код выглядит так, как-будто вытащен из говнопроекта. И да, на пальцах там ничего не объяснить.
Ты на свой посмотри "template inline"
_>>Каждая строчка выполняет какое-то одно осмысленное действие. M>Не одно, а кучу.
И чему это противоречит? Если для осмысленного действия надо сделать кучу элементарных операций.
_>>То что в С++ для отдельных осмысленных операций приходится писать много букв это издержки конкретного языка. M>Это не так.
Это очень даже так. Посмотри на темы которые обсуждаются в последнее время. Как правильно писать for — дожили
M>Ты просто видимо привык, что какой-то узкий спектр твоих задач хорошо покрывается средствами используемого тобой языка.
Грусть печаль, спектр моих задач не покрывается одними только языками и программированием.
M>Тебе повезло, что твой язык хорошо подходит под твои задачи
Да я везучий
Здравствуйте, kov_serg, Вы писали:
M>>Твой код выглядит так, как-будто вытащен из говнопроекта. И да, на пальцах там ничего не объяснить. _>Ты на свой посмотри "template inline"
Здравствуйте, Marty, Вы писали: M>>>Твой код выглядит так, как-будто вытащен из говнопроекта. И да, на пальцах там ничего не объяснить. _>>Ты на свой посмотри "template inline" M>А что не так?
да всё зашибись просто на надо было constexpr и __forceinline для шаблона то иначе не айс
Если бы не использовл C с классами, а хотя бы C++11 то написал бы как-то так:
Здравствуйте, kov_serg, Вы писали:
_>Здравствуйте, Marty, Вы писали:
M>>>>Твой код выглядит так, как-будто вытащен из говнопроекта. И да, на пальцах там ничего не объяснить. _>>>Ты на свой посмотри "template inline"
M>>А что не так? _>[cut=да всё зашибись просто на надо было constexpr и __forceinline для шаблона то иначе не айс] _>Если бы не использовл C с классами, а хотя бы C++11 то написал бы как-то так:
Не пойму что ты хочешь сказать. Я просто переписал твой код нормально, не более того.
Здравствуйте, Marty, Вы писали:
M>>>Не пойму что ты хочешь сказать. Я просто переписал твой код нормально, не более того. _>>Зачем?
M>Чтобы показать, насколько по-разному можно написать одно и то же
Я рад за вас. У вас всё получилось.
Другой вопрос: Как бы вы написали функцию расчета объёма тетраидера у которого известны все 6 сторон на С++?
Здравствуйте, kov_serg, Вы писали:
M>>Чтобы показать, насколько по-разному можно написать одно и то же _>Я рад за вас. У вас всё получилось.
_>Другой вопрос: Как бы вы написали функцию расчета объёма тетраидера у которого известны все 6 сторон на С++?
Для начала бы уточнил ТЗ и узнал бы, что подразумевается по термином "тетраидер"
Здравствуйте, Marty, Вы писали:
M>Для начала бы уточнил ТЗ и узнал бы, что подразумевается по термином "тетраидер"
Одна точка над треугольником соединяется 3 сторонами с вершинами треугольника.
Известные 3 стороны треугольника a,b,c и длины ea,eb,ec (ea напротив a, eb напротив b, ec напротив c)
Здравствуйте, kov_serg, Вы писали:
M>>Для начала бы уточнил ТЗ и узнал бы, что подразумевается по термином "тетраидер" _>Одна точка над треугольником соединяется 3 сторонами с вершинами треугольника. _>Известные 3 стороны треугольника a,b,c и длины ea,eb,ec (ea напротив a, eb напротив b, ec напротив c) _>Image: 254px-Tetrahedron.gif
subroutine quart(n,c,r4,jj,mm)
c use the procedure of la-4299 to solve the quartic equation
c x**4+b*x**3+c*x**2+d*x+e=0 (c(i),i=1,5)=1,b,c,d,e
c the jj real roots are returned in r4. the roots with odd
c multiplicity are listed first, in ascending order. if mm=0,
c the roots with even multiplicity are omitted.
implicit double precision (a-h,o-z)
dimension c(5),r4(4),tp(16)
parameter (pf=(2.*3.1415926535898d0)/3.,th=1d0/3.)
c
jj=0
if(n.eq.3)go to 90
c
c let y=x+b/4 to reduce the quartic equation to
c y**4+q*y**2+r*y+s=0 (tp(i),i=1,5)=b/2,b/4,q,r,s
tp(1)=.5*c(2)
tp(2)=.25*c(2)
tp(3)=c(3)-1.5*tp(1)**2
tp(4)=c(4)+tp(1)*(tp(1)**2-c(3))
tp(5)=c(5)-.0625*tp(1)*(5.*c(4)-c(3)*tp(1)+3.*tp(4))
c
c steps 2-7 (la-4299) (tp(i),i=6,11)=b/3,c,d,p/3,q/2,w
if(abs(tp(4)).le.1.e-10*max(abs(c(4)),tp(1)**2,abs(tp(1)*c(3))))
1 go to 40
tp(6)=2.*th*tp(3)
tp(7)=tp(3)**2-4.*tp(5)
tp(8)=-tp(4)**2
tp(9)=th*tp(7)-tp(6)**2
tp(10)=.5*(tp(8)-tp(6)*(tp(7)-2.*tp(6)**2))
tp(11)=tp(9)**3+tp(10)**2
if(abs(tp(11)).le.1.e-10*max(abs(tp(9)**3),tp(10)**2))go to 10
if(tp(11).gt.0.)go to 30
tp(12)=sqrt(-tp(9))
if(tp(6).ge.0..or.tp(7).le.0.)return
tp(13)=-tp(10)/tp(12)**3
if(abs(tp(13)).ge.1.)go to 10
tp(13)=acos(tp(13))
tp(14)=2.*tp(12)*cos(th*tp(13))-tp(6)
if(tp(14).lt.1.e-10*abs(tp(6)))go to 40
tp(15)=.5*sqrt(tp(14))
tp(14)=-tp(14)-3.*tp(6)
tp(16)=tp(4)/tp(15)
if(abs(tp(16)).ge.tp(14))go to 10
jj=4
tp(13)=.5*sqrt(tp(14)+tp(16))
r4(1)=-tp(13)-tp(15)-tp(2)
r4(2)=tp(13)-tp(15)-tp(2)
tp(13)=.5*sqrt(tp(14)-tp(16))
r4(3)=tp(15)-tp(13)-tp(2)
r4(4)=tp(15)+tp(13)-tp(2)
return
c
c steps 8-11 (la-4299) double or triple roots.
10 tp(12)=sign(sqrt(abs(tp(9))),tp(10))
tp(13)=-2.*tp(12)-tp(6)
tp(14)=tp(12)-tp(6)
tp(15)=sign(.5*sqrt(abs(tp(13))),tp(4))
if(tp(14).le.0.)go to 20
tp(16)=sqrt(tp(14))
jj=2
r4(1)=-tp(15)-tp(2)-tp(16)
r4(2)=tp(16)-tp(15)-tp(2)
if(mm.eq.0)return
if(tp(10).eq.0.)return
jj=3
r4(3)=tp(15)-tp(2)
return
20 if(mm.eq.0)return
jj=1
r4(1)=-tp(15)-tp(2)
return
c
c step 12 (la-4299)
30 tp(12)=-tp(10)-sign(sqrt(tp(11)),tp(10))
tp(12)=sign(abs(tp(12))**th,tp(12))
tp(14)=tp(12)-tp(9)/tp(12)-tp(6)
if(tp(14).lt.1.e-10*abs(tp(6)))go to 40
tp(15)=.5*sign(sqrt(tp(14)),tp(4))
tp(16)=abs(tp(4)/tp(15))-tp(14)-3.*tp(6)
if(tp(16).le.0.)return
tp(16)=.5*sqrt(tp(16))
jj=2
r4(1)=-tp(16)-tp(15)-tp(2)
r4(2)=tp(16)-tp(15)-tp(2)
return
c
c steps 13-24 (la-4299) trivial case; r=tp(4)=0
40 tp(6)=.5*tp(3)
tp(7)=tp(6)**2-tp(5)
tp(9)=1.e-8*max(tp(6)**2,abs(tp(5)))
if(tp(7).le.tp(9))go to 60
tp(8)=sqrt(tp(7))
tp(16)=tp(8)-tp(6)
if(tp(16).le.0.)go to 70
tp(15)=-tp(6)-tp(8)
tp(16)=sqrt(tp(16))
if(tp(15).gt.0.)go to 50
jj=2
r4(1)=-tp(16)-tp(2)
r4(2)=tp(16)-tp(2)
if(mm.eq.0)return
if(tp(15).ne.0.)return
jj=3
r4(3)=-tp(2)
return
50 tp(15)=sqrt(tp(15))
jj=4
r4(1)=-tp(16)-tp(2)
r4(2)=-tp(15)-tp(2)
r4(3)=tp(15)-tp(2)
r4(4)=tp(16)-tp(2)
return
60 if(mm.eq.0)return
if(tp(7).lt.-tp(9).or.tp(6).gt.0.)return
if(tp(6).eq.0.)go to 80
jj=2
tp(16)=sqrt(-tp(6))
r4(1)=tp(16)-tp(2)
r4(2)=-tp(16)-tp(2)
return
70 if(mm.eq.0)return
if(tp(16).lt.0.)return
80 jj=1
r4(1)=-tp(2)
return
c
c cubic equation. x**3+b*x**2+c*x+d=0 (c(i),i=1,4)=1,b,c,d
c let y=x+b/3. then y**3+p*y+q=0 (tp(i),i=1,4)=b/3,p/3,q/2,w
90 tp(1)=th*c(2)
tp(2)=th*c(3)-tp(1)**2
tp(3)=.5*(c(4)-tp(1)*(c(3)-2.*tp(1)**2))
tp(4)=tp(2)**3+tp(3)**2
if(tp(4).gt.0.)go to 110
if(tp(4).eq.0.)go to 100
c
c case i (la-4299) 3 distinct roots
tp(5)=2.*sqrt(-tp(2))
tp(6)=8.*tp(3)/tp(5)**3
if(abs(tp(6)).ge.1.)go to 100
tp(7)=th*acos(-tp(6))
r4(1)=tp(5)*cos(pf+tp(7))-tp(1)
r4(2)=tp(5)*cos(pf-tp(7))-tp(1)
r4(3)=tp(5)*cos(tp(7))-tp(1)
jj=3
return
c
c case ii (la-4299) 1 distinct and 1 double root
100 r4(1)=-2.*sign(sqrt(-tp(2)),tp(3))-tp(1)
jj=1
if(mm.eq.0)return
if(r4(1).eq.0.)return
jj=2
r4(2)=-.5*r4(1)
return
c
c case iii (la-4299) 1 distinct root
110 tp(5)=-tp(3)-sign(sqrt(tp(4)),tp(3))
tp(5)=sign(abs(tp(5))**th,tp(5))
r4(1)=tp(5)-tp(2)/tp(5)-tp(1)
jj=1
return
end