Форум на Kuban.ru (http://forums.kuban.ru/)
-   Разработка программ (http://forums.kuban.ru/f1024/)
-   -   if x = 0 then res := 0 else res := 1 -> как? (http://forums.kuban.ru/f1024/if_x_%3D_0_then_res_%3D_0_else_res_%3D_1_-_kak-2889225.html)

Rat 31.07.2012 19:24

if x = 0 then res := 0 else res := 1 -> как?
 
Дано целое положительное число X от 0 n. Существует ли такая операция (функция и т.д.), результатом которой будет 0, если X=0 и 1, если X > 0? Что-то не придумаю.

wayerr 31.07.2012 19:38

[url]http://en.wikipedia.org/wiki/Sign_function[/url]

wayerr 31.07.2012 19:40

в языках программирования оноже [url]http://docs.oracle.com/javase/6/docs/api/java/lang/Math.html#signum%28double%29[/url]

NTFS_ 31.07.2012 20:06

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

Rat 31.07.2012 20:16

sign так же и работает. хочу без оператора условного перехода, либо доказать, что это невозможно. чота ума не хватает.

Rat 31.07.2012 20:18

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

tcode 31.07.2012 20:37

Один вопрос, а зачем тебе такая функция? Чем тебе переход не нравится?

Не хочешь переход можешь использовать сдвиги и or
или
можешь использовать деление самого на себя и ловить exception при делении на ноль, правда та будет дофига переходов вставленных компилятором ;)

А вообще от чего так торкает ;)

Rat 31.07.2012 20:41

exception суть тот же переход. сдвиги и т.п. это тоже алгоритмы, а я хочу математику. из спортивного интереса. типа как поменть a и b местами без третей переменой. дано число, к нему можно применить любые арифметические и функциональные преобразования - и больше никак. неужели нет решения? : )

tcode 31.07.2012 20:49

при условии что всегда X >=0

var
x:Byte;
y:Byte;
begin
x:=100;
y:=ord(x >0);
x:=0;
y:=ord(x >0);
end;

Unit1.pas.30: x:=100;
00452168 C645FB64 mov byte ptr [ebp-$05],$64
Unit1.pas.31: y:=ord(x >0);
0045216C 807DFB00 cmp byte ptr [ebp-$05],$00
00452170 0F97C0 setnbe al
00452173 8845FA mov [ebp-$06],al
Unit1.pas.32: x:=0;
00452176 C645FB00 mov byte ptr [ebp-$05],$00
Unit1.pas.33: y:=ord(x >0);
0045217A 807DFB00 cmp byte ptr [ebp-$05],$00
0045217E 0F97C0 setnbe al
00452181 8845FA mov [ebp-$06],al
Unit1.pas.35: end;

Переходов нет ;)

dax 31.07.2012 21:05

незнаю на бэйсине решается все очень просто

Dim a As Boolean
Dim x As Variant
x = 255
a = x

Rat 31.07.2012 21:06

я так понимаю тут используется порядковый номер false (0) и true (1). это работает, но не честно (зависит от реализации? или я не совсем понял)

Rat 31.07.2012 21:08

(9) и (8) аналогичны. tcode привел элегантный хак : ) однако это хак.

wayerr 31.07.2012 21:23

5-Rat >

там в википедии написано про элементарные функции и способы представления

wayerr 31.07.2012 21:30

если задача спортивная и хренение числа, например байт, то както так (на жаве)

(-i&128)/128

только работать будет от 0 до 128

Rat 31.07.2012 22:04

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

wayerr 31.07.2012 22:23

14-Rat >

емнип кусочно заданную функцию через полином не выразить.

wayerr 31.07.2012 22:44

13->wayerr > (-i&128)/128

я идиот, просто, без деления

((-i) >> 8) & 1

Ansv 31.07.2012 23:06

а может что-то с cos(2"пи"*x) замутить?

Ansv 31.07.2012 23:09

ой, только не 2 пи, а пи/2
ну и типа по модулю взять

tcode 01.08.2012 01:26

to0 Вообще есть такая книжка: Генри Уоррен "Алгоритмические трюки для программистов" вот в ней подобные вещи и рассматриваются.
например: для функции sign там приводят следующую реализацию
-(x >> 31)|(-x >> 31)

на Delphi это будет выглядеть так
var
d:integer;
y:integer;
begin
d:=-1000;
y:=-(d shr 31) or (-d shr 31);
d:=0;
y:=(-(d shr 31)) or (-d shr 31);
end;

tcode 01.08.2012 01:34

ps но мне мой вариант нравиться больше, так как он занимает всего две машинные команды cmp и setnbe

Да в книжке есть еще вариант короче для знакового сдвига - там будет не 5 действий, а 4. Вообще там много подобных решений и есть такие что без пол-литра не поймешь. Я бы предпочел в 98% использовать более простое и понятное решение чем то что приведено в этой книге, пусть даже оно бы и медленней работало;)

tcode 01.08.2012 01:53

pps для случая положительных чисел, для хранения которых используется тип со знаком формулу можно еще упростить до
-x >> 31

Rat 01.08.2012 11:05

(17) Логичнее не cos, а sin, но фнукция периодическая, придется еще доказать, что при любом X она не обратися в 0, кроме когда X = 0. А так да, для любого натурального X подойдет abs(sin(x)), я об этом уже думал, в принципе должно работать в 99,999% случаев.

Ansv 01.08.2012 11:45

22-Rat > насчет синуса согласна, уже просто туплю и путаю его с косинусом, а рыться в поисках истины некайф:)
Но причем тут [quote=Rat;26194747]придется еще доказать, что при любом X она не обратися в 0, кроме когда X = 0.[/quote]
Приведи еще пример, при каком х она обратится в 0, если у нее все аргументы будут кратны пи/2, ее значение может быть или 1, или -1.

Rat 01.08.2012 13:35

при том что sin(x) = 0 при x кратному pi, в том числе при x=0. ход конем в том, что константа pi - сильно не целая, и врядли когда x кратно pi для натуральных x, кроме 0. но это, строго говоря, не очевидно.

Rat 01.08.2012 13:47

проверил sin(x) для x=1..2147483647 - нет нулей. для 32-битных чисел с знаком, таким образом, способ работает. будет ли более элегантные варианты?

Rat 01.08.2012 13:49

т.е. рабочий вариант будет примерно такой: trunc(sin(x) + 1 - 0.00000000000001)

tcode 01.08.2012 14:18

to 26 а как же условие без прыжков.
у тебя же как минимум вызов двух функция и соответственно будут и call и ret.

tcode 01.08.2012 14:20

опечатка
функция - читать как функций

Rat 01.08.2012 16:25

про безусловные переходы я ничего не говорил : )
кстати + к26, надо синус еще в abs взять.

TCTF_AiS 03.08.2012 15:28

res = CInt(Abs(CBool(x)))

tcode 04.08.2012 01:10

to30 расслабься автора уже давно отпустило и больше так не торкает ;)
Даже слабо представляю где он свое решение будет использовать. Одно дело, если бы он так пытался оптимизировать некий кусок процедуры, что вызывает дофига раз и сильно сказывается на производительности. И вот он запустил какой нибудь очень дорогой профилировщик и вооружившись книжкой касперского по технике оптимизации использования памяти пытался избавиться от лишнего условного перехода, разворачивал циклы, выравнивал данные в памяти и.т.п. Но здесь этим даже не пахнет.


Текущее время: 22:36. Часовой пояс GMT +3.