current fuckup

olega

Что, по-вашему, выведет следующий код:

#include <boost/lexical_cast.hpp>

int main {
uint8_t u8 = 1;
uint16_t u16 = 2;
uint32_t u32 = 3;
uint64_t u64 = 4;

std::cerr << boost::lexical_cast<std::string>(u8) << std::endl;
std::cerr << boost::lexical_cast<std::string>(u16) << std::endl;
std::cerr << boost::lexical_cast<std::string>(u32) << std::endl;
std::cerr << boost::lexical_cast<std::string>(u64) << std::endl;

return 0;
}

Вот то-то и оно!

olega

И да, как же без него:

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!”

Werdna

boost::lexical_cast
Объясните мне тупому, зачем это нужно?
Почему нельзя просто snprintf? Ведь по скорости отличается на порядок.

Ivan8209

> Почему нельзя просто snprintf? Ведь по скорости отличается на порядок.
Потому что хочется писать такие элементарные вещи за один конструкт,
а не городить огород на каждый чих. И скорости тут ни при чём,
тут, вон, некоторые на питонах пишут.
---
"Люди недалёкие обычно осуждают всё, что выходит за пределы их понимания."

karkar

Аллах не велит использовать сишные функции там, где есть божественные потоки и операторы!

Garryss


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;

olega

Документация не для ковбоев!

zya369

Ведь по скорости отличается на порядок.
прямо так и на порядок?

istran

FYI, в C++11 появился std::to_string, для конвертиртации чисел в std::string, и std::sto{i,l,ll,ul,ull,f,d,ld}, для конвертации в обратную сторону.

istran

Почему нельзя просто snprintf?
Ну давай, напиши корректный пример с использованием snprintf, который сконвертит int в std::string.

elenangel

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

elenangel

порядок равен двум.

zya369

порядок равен двум.

в сто раз быстрее что ли?
std::string stringFormat(const std::string fmt, ...) ...

это все прекрасно, но
 string xxx = "asdasd";
string s = stringFormat("%s", xxx); // fail

 string s = stringFormat("%s", 13); // очепятка и привет! 

:(

zya369

ах да, еще забыл
 
void print(const string& s) {
...
stringFormat(s);
...
}

и потом счастье в светлом будущем

Werdna

померь, лексикал каст именно что на порядок.

zya369

да ты, небось, теплое с мягким сравнивал
 

$ 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 раза.
конечно, в двоичной системе это и есть "на порядок", но вряд ли ты это имел в виду :D

Maurog

теплое с мягким
можно еще добавить сюда форматирование double ? очень наглядно показывает результаты

smit1

да ты, небось, опять теплое с мягким сравнивал
В словах Пианиста есть доля правды - просто он делал такое же сравнение лет 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 :-)

Dasar

то бишь в 2 раза.
так это и есть на порядок.. двоичный.. )

zya369

так это и есть на порядок.. двоичный.. )
ты точно до конца прочитал?)
ЗЫ по просьбам
 $ 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

Dasar

ты точно до конца прочитал?)
мне, казалось, что да, но сейчас уже не уверен )

PITACHOK

Господа! Разве можно плюсовый (а тем более бустовый) код собирать без оптимизаций?!
С -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

elenangel

string xxx = "asdasd"; string s = stringFormat("%s", xxx); // fail
так %s это char*, а ты string передал
как вводить кастомные %ъ или переопределять стандартные я не знаю - это надо самому vsnprintf реализовывать

zya369

так %s это char*, а ты string передал
спасибо, кэп!

elenangel

ну передача по ссылке это уже придирки. решение понятно, а такие мелочи вылавливаются или компилятором в виде варнинга или каким-либо инструментом статического анализа

zya369

не, придирки к передаче по ссылке там не было, а было то, что где-нибудь потом ты передашь в print строчку, содержащую %s, и получишь счастье

zya369

как тут выше уточнили - с оптимизацией по времени разницы нет, ваш любимый *s*printf - весьма error-prone и должен идти на юг

elenangel

а, ну так если я случайно на целый ноль поделю или нулевой указатель разыменую - тоже получу счастье. у каждой функции есть ограничения и не надо их нарушать.

Dasar

а, ну так если я случайно на целый ноль поделю или нулевой указатель разыменую - тоже получу счастье.
желательно, кол-во таких возможностей уменьшать, а не увеличивать.

elenangel

ну то есть вообще не использовать указатели и деление?

elenangel

короче, надо просто не писать говнокод делать так:

void print(const string& s) {
...
stringFormat("%s", s.c_str;
...
}

zya369

надо просто не писать говнокод
сложно спорить :grin:
просто зачем писать код, который заведомо error-prone и еще и менее удобный?

Dasar

ну то есть вообще не использовать указатели и деление?
при разименовании нулевого указателя и делении на ноль - будет понятная и предсказуемая ошибка с небольшим разбросом поведения, никакого особого пиздеца не будет.
а вот printf(random-format-string) ведет себя слабо предсказуемым образом с высоким разбросом поведения.

elenangel

вы просили пример конвертации int в string через snprintf - у меня случайно валялась такая заготовка.
error-prone не более чем исходный snprintf
менее удобный чем что?

Ivan8209

Есть такое дело, что код, который создаётся плюсами, не всегда удобный.
А с учётом того, что нынче аргументы и строка формата проверяются,
то твоё утверждение о подверженности ошибкам работает как раз за printf,
так как системы типов в сях и приплюснутых сях на деле одинаково
недостаточно безопасны, но в сях типы хотя бы разрешимы.
---
"Люди недалёкие обычно осуждают всё, что выходит за пределы их понимания."

zya369

менее удобный чем что?
если для конвертации int в string, то чем std::to_string (или lexical_cast)

elenangel

std::to_string

c++11 only
(или lexical_cast)
boost, лишняя внешняя зависимость

olega

Вот какая шняга получилась в итоге:

#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!

bleyman

x = rand;
Имей в виду, что rand по непонятной причине может тормозить как неизвестно что. Я на это как-то напоролся когда эффективность malloc/free мерял, а потом обнаружил что и в gcc, и вижуалстудии rand занимал чуть более 50% времени.

Anturag

x = rand;
Имей в виду, что rand по непонятной причине может тормозить как неизвестно что. Я на это как-то напоролся когда эффективность malloc/free мерял, а потом обнаружил что и в gcc, и вижуалстудии rand занимал чуть более 50% времени.
А причём тут gcc? :confused:

Ivan8209

Наверное, потому что в GCC можно засадить свой код, который
будет обрабатывать rand специальным образом.
---
"Это глупость вообще, но мне это знакомая песня."

Anturag

Ну так можно, конечно, но в чём смысл так сложно делать и какова вероятность того, что это было так сделано? Тем более наличие такого необъяснимого извращения проверяется по GPLv2+, ну или дизассемблированием.

Maurog

Имей в виду, что rand
кстати, недавно посмотрел интересную лекцию от STL про rand: http://channel9.msdn.com/Events/GoingNative/2013/rand-Consid...
немного категоричные заявления, но в целом занятно и полезно

Maurog

rand по непонятной причине может тормозить как неизвестно что
могу предположить, что это из-за tls, где хранится seed. сам по себе алгоритм там обычно шустрый (сдвиги, да суммы)

Whoman-in-white

boost, лишняя внешняя зависимость
в этом есть что-то плохое?

elenangel

да, когда надо собирать под древний редхат

olega

Апну тему.

(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 были разных типов.

agaaaa

Интересно подумать о том, как избегать такого впредь. Мне видятся два варианта:
- дать осмысленные имена переменным, если возможно.
- провеку нахождения в границах вынести в отдельную функцию.
- писать юнит-тесты к таким функциям

6yrop

Интересно подумать о том, как избегать такого впредь.
применять надежную схему копипаста.
Надежная это когда последовательность действий такая, в которой вероятность ошибки близка к нулю.

agaaaa

применять надежную схему копипаста.
:shocked:

6yrop

что с тобой? ты стал удивляться элементарным действиям с текстом?

agaaaa

что с тобой? ты стал удивляться элементарным действиям с текстом?
Я стал удивляться количеству предполагаемого (или предлагаемого?) копипаста. А как же DRY?

apl13

1. Перейти от (i >= i_min) && (i <= k_max) к (i[0] >= i_min[0]) && (i[0] <= i_max[2])

6yrop

а что не?
 
 
(i.value >= i.min) && (i.value <= k.max)

и сделать из этого функцию:
WithinBoundaries {
    return (value >= min) && (value <= max);
}

PooH

 
 

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;


а все дело в лени и преждевременной оптимизации

olega

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

olega

надежную схему копипаста
О, а это идея!

#define CHECK(var) var >= var ## _min) && (var <= var ## _max
CHECK(i) && CHECK(j) && CHECK(k)
#undef CHECK

Dasar

имхо, это всё дуть на воду.
когда цена вопроса - неделя ожидания, то, в любом случае, не обойтись без внятных тестовых прогонов на задачах меньшего размера для того, чтобы убедиться, что программа вообще работоспособна.

yroslavasako

2. Сделать шаблонную обертку над численными типами так, чтобы i, j и k были разных типов.
вот это, кстати, интересный вопрос. Как сделать шаблонную обёртку так, чтобы при преобразвоании базиса менялись типы?

karkar

Беда в том, что программа с подобным багом может быть вполне работоспособна, и баг может прятаться незамеченным довольно долго. У меня самого недавно вот такой реально фикс был для бага, несколько месяцев сидевшего в коде:

Не тот индекс в выражении приводил к слегка другим данным, возвращаемым функцией, что приводило к слегка другим решениям вызывавшего алгоритма: вектора движения иногда выбирались не оптимальные, что приводило к чуть худшему качеству картинки. Само наличие бага обнаружилось лишь после того, как в процессе оптимизации была сделана другая реализация той же функции и для тестирования было решено проверить, что оптимизированная ф-я дает те же ответы что и старая. Внезапно оказалось, что результаты разные, потому что новая реализация корректная, а в старой сидел баг.

Dasar

полноценный же тестовый прогон получается ты не делал. Корректность результата оценивал на глаз, а не ручным (или дублирующим) расчетом

rosali

> программа с подобным багом может быть вполне работоспособна, и баг может прятаться незамеченным довольно долго
Вспоминаю случай, когда я в формате дат спутал M и m и у меня месяцы подставлялись в минуты =) И ничего, годы проработало прежде чем заметили :D

karkar

Да, верно, грешен. Как-то поленился вручную миллионы операций делать.
Это, кстати, вообще интересный вопрос: как кошерно тестировать алгоритмы обработки видео, где идет поиск, и правильный результат на реальных данных заведомо неизвестен, а на синтетических данных такую ошибку можно и не поймать?

SPARTAK3959

PVS студия рекламирует, что может найти некоторые из багов порожденные неправильной копипастой.

kill-still

mvel коварен.
Коллега пришёл с вопросом почему он передаёт '{}', а моя система возвращает ему '[]'. Час тупил, прежде чем посмотреть тип {}.getClass - [Ljava.lang.Object; Так что оказалось, что факапа не было.
З.Ы. надо писать 'new HashMap'.

Realist

Дык то ж Yourself. А копипаста — это Google Driven Development!

schipuchka1

Это, кстати, вообще интересный вопрос: как кошерно тестировать алгоритмы обработки видео, где идет поиск, и правильный результат на реальных данных заведомо неизвестен, а на синтетических данных такую ошибку можно и не поймать?
На большом телевизоре :)
ну а вообще как сказали выше - статическая проверка кода + написание так чтобы обфускатор не делал код понятнее.

karkar

TDD - Телевизор Driven Development ;)
Оставить комментарий
Имя или ник:
Комментарий: