current fuckup
Fukuppy says: “I fly around on my awesome wings, patrolling supermarket showcases and kitchen refrigerators. I can talk to vegetables, fruit, meat, and fish and can check on their health!”
boost::lexical_castОбъясните мне тупому, зачем это нужно?
Почему нельзя просто snprintf? Ведь по скорости отличается на порядок.
Потому что хочется писать такие элементарные вещи за один конструкт,
а не городить огород на каждый чих. И скорости тут ни при чём,
тут, вон, некоторые на питонах пишут.
---
"Люди недалёкие обычно осуждают всё, что выходит за пределы их понимания."
Аллах не велит использовать сишные функции там, где есть божественные потоки и операторы!
Question: What does lexical_cast<std::string> of an int8_t or uint8_t not do what I expect?
Answer: As above, note that int8_t and uint8_t are actually chars and are formatted as such. To avoid this, cast to an integer type first: lexical_cast<std::string>(static_cast<int>(n;
Ведь по скорости отличается на порядок.прямо так и на порядок?
FYI, в C++11 появился std::to_string, для конвертиртации чисел в std::string, и std::sto{i,l,ll,ul,ull,f,d,ld}, для конвертации в обратную сторону.
Почему нельзя просто snprintf?Ну давай, напиши корректный пример с использованием snprintf, который сконвертит int в std::string.
std::string stringFormat(const std::string fmt, ...)
{
static const int baseSize = 64;
int size = fmt.size>0?fmt.size+1:baseSize;
std::vector<std::string::value_type> resultVector;
va_list ap;
for(;;)
{
resultVector.resize(size);
va_start(ap, fmt);
int n = vsnprintf(resultVector.data size, fmt.c_str ap);
va_end(ap);
if (n > -1 && n < size)
{
resultVector.resize(n);
return std::string(resultVector.begin resultVector.end;
}
if (n > -1)
{
size = n + 1;
}
else
{
size *= 2;
}
}
return std::string(resultVector.begin resultVector.end;
}
порядок равен двум.
порядок равен двум.
в сто раз быстрее что ли?
std::string stringFormat(const std::string fmt, ...) ...
это все прекрасно, но
string xxx = "asdasd";
string s = stringFormat("%s", xxx); // fail
string s = stringFormat("%s", 13); // очепятка и привет!
void print(const string& s) {
...
stringFormat(s);
...
}
и потом счастье в светлом будущем
померь, лексикал каст именно что на порядок.
$ export fff=1.cpp; cat $fff; g++ $fff && time ./a.out
#include <boost/lexical_cast.hpp>
#include <boost/uuid/uuid.hpp>
#include <iostream>
int main {
int x;
std::string s;
for(int i = 0; i < 1<<19; ++i) {
x = rand;
s = boost::lexical_cast<std::string>(x);
}
std::cerr << "Last = " << s << ", x = " << x << std::endl;
return 0;
}
Last = 1527356946, x = 1527356946
real 0m0.239s
user 0m0.236s
sys 0m0.000s
$ export fff=2.cpp; cat $fff; g++ $fff && time ./a.out
#include <boost/lexical_cast.hpp>
#include <boost/uuid/uuid.hpp>
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
int main {
// srandom(time(0;
char buf[20];
int x;
for(int i = 0; i < 1<<19; ++i) {
x = rand;
sprintf(buf, "%d", x);
}
std::cerr << "Last = " << buf << ", x = " << x << std::endl;
return 0;
}
Last = 1527356946, x = 1527356946
real 0m0.120s
user 0m0.116s
sys 0m0.000s
то бишь в 2 раза.
конечно, в двоичной системе это и есть "на порядок", но вряд ли ты это имел в виду
теплое с мягкимможно еще добавить сюда форматирование double ? очень наглядно показывает результаты
да ты, небось, опять теплое с мягким сравнивалВ словах Пианиста есть доля правды - просто он делал такое же сравнение лет 10 назад, когда реализация lexical_cast выглядела просто как-то так:
template<typename Target, typename Source>
Target lexical_cast(Source arg)
{
std::stringstream interpreter;
Target result;
if(!(interpreter << arg) ||
!(interpreter >> result) ||
!(interpreter >> std::ws).eof
throw bad_lexical_cast;
return result;
}
Можешь посмотреть, сколько сейчас в том коде специализаций и хаков, в т.ч. и вызовы snprintf :-)
то бишь в 2 раза.так это и есть на порядок.. двоичный.. )
так это и есть на порядок.. двоичный.. )ты точно до конца прочитал?)
ЗЫ по просьбам
$ cat clean.cpp
#include <boost/lexical_cast.hpp>
#include <boost/uuid/uuid.hpp>
#include <iostream>
int main {
int x;
std::string s;
unsigned long int res = 0;
for(int i = 0; i < 1<<19; ++i) {
x = rand;
res += x;
}
std::cerr << "res = " << res << std::endl;
return 0;
}
$ g++ clean.cpp ; time ./a.out
res = 563096650256685
real 0m0.011s
user 0m0.008s
sys 0m0.000s
ты точно до конца прочитал?)мне, казалось, что да, но сейчас уже не уверен )
С -O2 такие результаты:
$ time ./tst1
Last = 1527356946, x = 1527356946
real 0m0.069s
user 0m0.064s
sys 0m0.004s
$ time ./tst2
Last = 1527356946, x = 1527356946
real 0m0.064s
user 0m0.060s
sys 0m0.004s
string xxx = "asdasd"; string s = stringFormat("%s", xxx); // failтак %s это char*, а ты string передал
как вводить кастомные %ъ или переопределять стандартные я не знаю - это надо самому vsnprintf реализовывать
так %s это char*, а ты string передалспасибо, кэп!
ну передача по ссылке это уже придирки. решение понятно, а такие мелочи вылавливаются или компилятором в виде варнинга или каким-либо инструментом статического анализа
не, придирки к передаче по ссылке там не было, а было то, что где-нибудь потом ты передашь в print строчку, содержащую %s, и получишь счастье
как тут выше уточнили - с оптимизацией по времени разницы нет, ваш любимый *s*printf - весьма error-prone и должен идти на юг
а, ну так если я случайно на целый ноль поделю или нулевой указатель разыменую - тоже получу счастье. у каждой функции есть ограничения и не надо их нарушать.
а, ну так если я случайно на целый ноль поделю или нулевой указатель разыменую - тоже получу счастье.желательно, кол-во таких возможностей уменьшать, а не увеличивать.
ну то есть вообще не использовать указатели и деление?
void print(const string& s) {
...
stringFormat("%s", s.c_str;
...
}
надо просто не писать говнокодсложно спорить
просто зачем писать код, который заведомо error-prone и еще и менее удобный?
ну то есть вообще не использовать указатели и деление?при разименовании нулевого указателя и делении на ноль - будет понятная и предсказуемая ошибка с небольшим разбросом поведения, никакого особого пиздеца не будет.
а вот printf(random-format-string) ведет себя слабо предсказуемым образом с высоким разбросом поведения.
error-prone не более чем исходный snprintf
менее удобный чем что?
А с учётом того, что нынче аргументы и строка формата проверяются,
то твоё утверждение о подверженности ошибкам работает как раз за printf,
так как системы типов в сях и приплюснутых сях на деле одинаково
недостаточно безопасны, но в сях типы хотя бы разрешимы.
---
"Люди недалёкие обычно осуждают всё, что выходит за пределы их понимания."
менее удобный чем что?если для конвертации int в string, то чем std::to_string (или lexical_cast)
std::to_string
c++11 only
(или lexical_cast)boost, лишняя внешняя зависимость
#include <boost/lexical_cast.hpp>
template <typename String>
class interpolate {
public:
interpolate(const String &s): text(s current_arg(0) {}
template <typename T, typename... Rest>
String args(T value, Rest... rest) {
replace(current_arg, boost::lexical_cast<String>(value;
current_arg++;
return args(rest...);
}
String args {
return text;
}
operator String {
return text;
}
private:
void replace(unsigned int where, String s) {
String target = "{" +
boost::lexical_cast<String>(where) + "}";
size_t pos, len;
len = target.length;
whilepos=text.find(target != String::npos) {
text.replace(pos, len, s);
}
}
String text;
unsigned int current_arg;
};
typedef interpolate<std::string> interpolate_s;
#include <iostream>
int main {
std::cout << interpolate_s("{0} - {1} - `{2}' - {1} - {0}").args(int(1 float(2.25f "3") << std::endl;
return 0;
}
Mach mit, mach’s nach, mach’s besser!
x = rand;Имей в виду, что rand по непонятной причине может тормозить как неизвестно что. Я на это как-то напоролся когда эффективность malloc/free мерял, а потом обнаружил что и в gcc, и вижуалстудии rand занимал чуть более 50% времени.
А причём тут gcc?x = rand;Имей в виду, что rand по непонятной причине может тормозить как неизвестно что. Я на это как-то напоролся когда эффективность malloc/free мерял, а потом обнаружил что и в gcc, и вижуалстудии rand занимал чуть более 50% времени.
будет обрабатывать rand специальным образом.
---
"Это глупость вообще, но мне это знакомая песня."
Ну так можно, конечно, но в чём смысл так сложно делать и какова вероятность того, что это было так сделано? Тем более наличие такого необъяснимого извращения проверяется по GPLv2+, ну или дизассемблированием.
Имей в виду, что randкстати, недавно посмотрел интересную лекцию от STL про rand: http://channel9.msdn.com/Events/GoingNative/2013/rand-Consid...
немного категоричные заявления, но в целом занятно и полезно
rand по непонятной причине может тормозить как неизвестно чтомогу предположить, что это из-за tls, где хранится seed. сам по себе алгоритм там обычно шустрый (сдвиги, да суммы)
boost, лишняя внешняя зависимостьв этом есть что-то плохое?
да, когда надо собирать под древний редхат
(i >= i_min) && (i <= k_max) &&
(j >= j_min) && (j <= j_max) &&
(k >= k_min) && (k <= k_max);
Два дня жизни и неделя машинного времени впустую.
Интересно подумать о том, как избегать такого впредь. Мне видятся два варианта:
1. Перейти от i,j,k к i[3]
2. Сделать шаблонную обертку над численными типами так, чтобы i, j и k были разных типов.
Интересно подумать о том, как избегать такого впредь. Мне видятся два варианта:- дать осмысленные имена переменным, если возможно.
- провеку нахождения в границах вынести в отдельную функцию.
- писать юнит-тесты к таким функциям
Интересно подумать о том, как избегать такого впредь.применять надежную схему копипаста.
Надежная это когда последовательность действий такая, в которой вероятность ошибки близка к нулю.
применять надежную схему копипаста.
что с тобой? ты стал удивляться элементарным действиям с текстом?
что с тобой? ты стал удивляться элементарным действиям с текстом?Я стал удивляться количеству предполагаемого (или предлагаемого?) копипаста. А как же DRY?
1. Перейти от (i >= i_min) && (i <= k_max) к (i[0] >= i_min[0]) && (i[0] <= i_max[2])
(i.value >= i.min) && (i.value <= k.max)
и сделать из этого функцию:
WithinBoundaries {
return (value >= min) && (value <= max);
}
view = Matrix4x4(position).inverse;
if(ortho) {
projection.elems[0][0] = 2 / (r - l);
projection.elems[1][1] = 2 / (t - b);
projection.elems[2][2] = 2 / (farZ - nearZ);
projection.elems[3][0] = -(r + l) / (r - l);
projection.elems[3][1] = (t + b) / (t - b);
projection.elems[3][2] = -(farZ + nearZ) / (farZ - nearZ);
}
viewProjected = view * projection;
сначала было так
потом я добавил расчет проективных матриц для перспективного проецирования
вот так:
view = Matrix4x4(position).inverse;
if(ortho) {
projection.elems[0][0] = 2 / (r - l);
projection.elems[1][1] = 2 / (t - b);
projection.elems[2][2] = 2 / (farZ - nearZ);
projection.elems[3][0] = -(r + l) / (r - l);
projection.elems[3][1] = (t + b) / (t - b);
projection.elems[3][2] = -(farZ + nearZ) / (farZ - nearZ);
} else {
float S = 1.0F / tan(FOV / 2.0F);
projection.elems[0][0] = S;
projection.elems[1][1] = -S * AR;
projection.elems[2][2] = (farZ + nearZ) / (farZ - nearZ);
projection.elems[3][2] = -2.0F * farZ * nearZ / (farZ - nearZ);
projection.elems[2][3] = 1.0F;
projection.elems[3][3] = 0.0F;
}\
viewProjected = view * projection;
и у меня началась какая-то свистопляска
ортогональное проектирование перестало работать
ага, добавляю код, который вообще не должен вызываться для орто-проектирования и оно ломается
часа два потратил пока не дошло:
view = Matrix4x4(position).inverse;
projection.MakeIdentity;
if(ortho) {
projection.elems[0][0] = 2 / (r - l);
projection.elems[1][1] = 2 / (t - b);
projection.elems[2][2] = 2 / (farZ - nearZ);
projection.elems[3][0] = -(r + l) / (r - l);
projection.elems[3][1] = (t + b) / (t - b);
projection.elems[3][2] = -(farZ + nearZ) / (farZ - nearZ);
} else {
float S = 1.0F / tan(FOV / 2.0F);
projection.elems[0][0] = S;
projection.elems[1][1] = -S * AR;
projection.elems[2][2] = (farZ + nearZ) / (farZ - nearZ);
projection.elems[3][2] = -2.0F * farZ * nearZ / (farZ - nearZ);
projection.elems[2][3] = 1.0F;
projection.elems[3][3] = 0.0F;
}\
viewProjected = view * projection;
а все дело в лени и преждевременной оптимизации
1. Перейти от (i >= i_min) && (i <= k_max) к (i[0] >= i_min[0]) && (i[0] <= i_max[2])Не, не так. Вот:
bool ok = true;
for(int n = 0; n < MAGIC_3; ++n) {
if(i[n] < i_min[n] || i[n] > i_max[n]) {
ok = false;
break;
}
}
надежную схему копипастаО, а это идея!
#define CHECK(var) var >= var ## _min) && (var <= var ## _max
CHECK(i) && CHECK(j) && CHECK(k)
#undef CHECK
когда цена вопроса - неделя ожидания, то, в любом случае, не обойтись без внятных тестовых прогонов на задачах меньшего размера для того, чтобы убедиться, что программа вообще работоспособна.
2. Сделать шаблонную обертку над численными типами так, чтобы i, j и k были разных типов.вот это, кстати, интересный вопрос. Как сделать шаблонную обёртку так, чтобы при преобразвоании базиса менялись типы?
Не тот индекс в выражении приводил к слегка другим данным, возвращаемым функцией, что приводило к слегка другим решениям вызывавшего алгоритма: вектора движения иногда выбирались не оптимальные, что приводило к чуть худшему качеству картинки. Само наличие бага обнаружилось лишь после того, как в процессе оптимизации была сделана другая реализация той же функции и для тестирования было решено проверить, что оптимизированная ф-я дает те же ответы что и старая. Внезапно оказалось, что результаты разные, потому что новая реализация корректная, а в старой сидел баг.
полноценный же тестовый прогон получается ты не делал. Корректность результата оценивал на глаз, а не ручным (или дублирующим) расчетом
Вспоминаю случай, когда я в формате дат спутал M и m и у меня месяцы подставлялись в минуты =) И ничего, годы проработало прежде чем заметили
Это, кстати, вообще интересный вопрос: как кошерно тестировать алгоритмы обработки видео, где идет поиск, и правильный результат на реальных данных заведомо неизвестен, а на синтетических данных такую ошибку можно и не поймать?
PVS студия рекламирует, что может найти некоторые из багов порожденные неправильной копипастой.
Коллега пришёл с вопросом почему он передаёт '{}', а моя система возвращает ему '[]'. Час тупил, прежде чем посмотреть тип {}.getClass - [Ljava.lang.Object; Так что оказалось, что факапа не было.
З.Ы. надо писать 'new HashMap'.
Дык то ж Yourself. А копипаста — это Google Driven Development!
Это, кстати, вообще интересный вопрос: как кошерно тестировать алгоритмы обработки видео, где идет поиск, и правильный результат на реальных данных заведомо неизвестен, а на синтетических данных такую ошибку можно и не поймать?На большом телевизоре
ну а вообще как сказали выше - статическая проверка кода + написание так чтобы обфускатор не делал код понятнее.
TDD - Телевизор Driven Development
Оставить комментарий
olega
Что, по-вашему, выведет следующий код:Вот то-то и оно!