if x = 0 then res := 0 else res := 1 -> как? Дано целое положительное число X от 0 n. Существует ли такая операция (функция и т.д.), результатом которой будет 0, если X=0 и 1, если X > 0? Что-то не придумаю. |
[url]http://en.wikipedia.org/wiki/Sign_function[/url] |
в языках программирования оноже [url]http://docs.oracle.com/javase/6/docs/api/java/lang/Math.html#signum%28double%29[/url] |
Ну так определи себе функцию и используй ее. Делов-то на три минуты. К своему стыду и смеху, я как-то обнаружил, что почти треть функций модуля SysUtils у меня собственные - зато я не зависел от багов, которые там повставляли индусы от Borland, а только от своих собственных. |
sign так же и работает. хочу без оператора условного перехода, либо доказать, что это невозможно. чота ума не хватает. |
т.е. нужно решить задачу математически, а не алгоритмически. первое что пришло на ум - x в степени x, но я забыл школьные уроки алгебры - оказалось, что не прокатит. |
Один вопрос, а зачем тебе такая функция? Чем тебе переход не нравится? Не хочешь переход можешь использовать сдвиги и or или можешь использовать деление самого на себя и ловить exception при делении на ноль, правда та будет дофига переходов вставленных компилятором ;) А вообще от чего так торкает ;) |
exception суть тот же переход. сдвиги и т.п. это тоже алгоритмы, а я хочу математику. из спортивного интереса. типа как поменть a и b местами без третей переменой. дано число, к нему можно применить любые арифметические и функциональные преобразования - и больше никак. неужели нет решения? : ) |
при условии что всегда 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; Переходов нет ;) |
незнаю на бэйсине решается все очень просто Dim a As Boolean Dim x As Variant x = 255 a = x |
я так понимаю тут используется порядковый номер false (0) и true (1). это работает, но не честно (зависит от реализации? или я не совсем понял) |
(9) и (8) аналогичны. tcode привел элегантный хак : ) однако это хак. |
5-Rat > там в википедии написано про элементарные функции и способы представления |
если задача спортивная и хренение числа, например байт, то както так (на жаве) (-i&128)/128 только работать будет от 0 до 128 |
Ну это все однотипные решения. Да, они работают, будем считать, что задача решена наполовину. Надо думать над математическим способом. В идеале - получить выражение полиномиального вида. |
14-Rat > емнип кусочно заданную функцию через полином не выразить. |
13->wayerr > (-i&128)/128 я идиот, просто, без деления ((-i) >> 8) & 1 |
а может что-то с cos(2"пи"*x) замутить? |
ой, только не 2 пи, а пи/2 ну и типа по модулю взять |
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; |
ps но мне мой вариант нравиться больше, так как он занимает всего две машинные команды cmp и setnbe Да в книжке есть еще вариант короче для знакового сдвига - там будет не 5 действий, а 4. Вообще там много подобных решений и есть такие что без пол-литра не поймешь. Я бы предпочел в 98% использовать более простое и понятное решение чем то что приведено в этой книге, пусть даже оно бы и медленней работало;) |
pps для случая положительных чисел, для хранения которых используется тип со знаком формулу можно еще упростить до -x >> 31 |
(17) Логичнее не cos, а sin, но фнукция периодическая, придется еще доказать, что при любом X она не обратися в 0, кроме когда X = 0. А так да, для любого натурального X подойдет abs(sin(x)), я об этом уже думал, в принципе должно работать в 99,999% случаев. |
22-Rat > насчет синуса согласна, уже просто туплю и путаю его с косинусом, а рыться в поисках истины некайф:) Но причем тут [quote=Rat;26194747]придется еще доказать, что при любом X она не обратися в 0, кроме когда X = 0.[/quote] Приведи еще пример, при каком х она обратится в 0, если у нее все аргументы будут кратны пи/2, ее значение может быть или 1, или -1. |
при том что sin(x) = 0 при x кратному pi, в том числе при x=0. ход конем в том, что константа pi - сильно не целая, и врядли когда x кратно pi для натуральных x, кроме 0. но это, строго говоря, не очевидно. |
проверил sin(x) для x=1..2147483647 - нет нулей. для 32-битных чисел с знаком, таким образом, способ работает. будет ли более элегантные варианты? |
т.е. рабочий вариант будет примерно такой: trunc(sin(x) + 1 - 0.00000000000001) |
to 26 а как же условие без прыжков. у тебя же как минимум вызов двух функция и соответственно будут и call и ret. |
опечатка функция - читать как функций |
про безусловные переходы я ничего не говорил : ) кстати + к26, надо синус еще в abs взять. |
res = CInt(Abs(CBool(x))) |
to30 расслабься автора уже давно отпустило и больше так не торкает ;) Даже слабо представляю где он свое решение будет использовать. Одно дело, если бы он так пытался оптимизировать некий кусок процедуры, что вызывает дофига раз и сильно сказывается на производительности. И вот он запустил какой нибудь очень дорогой профилировщик и вооружившись книжкой касперского по технике оптимизации использования памяти пытался избавиться от лишнего условного перехода, разворачивал циклы, выравнивал данные в памяти и.т.п. Но здесь этим даже не пахнет. |
Текущее время: 22:36. Часовой пояс GMT +3. |