2015-06-12 1 views
0

Если предположить, что у меня есть a: usize и отрицательный b:isize как я добиваюсь следующая семантики - уменьшить по абсолютной величине Ь в быстром возможном способе?Быстрее способ добавления отрицательного подписал в беззнаковые

Я уже думал о a - (b.abs() as usize), но мне интересно, есть ли более быстрый способ. Может, что-то с бит-манипуляцией?

+1

Вы беспокоитесь о потенциальных недостатках? Возможно ли, что 'a' превысит максимально допустимое значение' isize'? –

+0

Не происходит ли переполнение, если 'a <| b |'? Я знаю о потенциальных недостатках и имеет решение, которое должно позаботиться об этом - результат будет использоваться для существенного разделения диапазона ('' '' '' '' действительно 'range.start' или' range.end' в зависимости от ' b'). Если я утверждаю, что 'range.start

+1

Если вы хотите что-то быстрее, я надеюсь, что вы уже выполнили тесты и заметили, что это слишком медленно. Затем вы можете предоставить нам контрольные показатели, чтобы мы знали, что любое предлагаемое решение выполняется быстрее. Даже просмотр списков сборок не говорит правду. Это всегда возможно (хотя и довольно маловероятно), например, что команда 'sub' имеет массивный конвейер. – Shepmaster

ответ

4

Почему вы предполагаете, что это медленно? Если этот код введен в функции и компиляции на x86-64 Linux, он генерирует следующее:

_ZN6simple20h0f921f89f1d823aeeaaE: 
    mov rax, rsi 
    neg rax 
    cmovl rax, rsi 
    sub rdi, rax 
    mov rax, rdi 
    ret 

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

Это не означает, что это определенно не может быть сделано быстрее, но я не убежден, что это можно сделать быстрее на много.

+0

Интересно, когда я положил его на rust.godbolt.org, я получил http://goo.gl/oiqDqW –

+0

Похоже, что он скомпилирован в режиме отладки с минимальными оптимизациями. Попробуйте https://play.rust-lang.org/ и не забудьте нажать «Отпустить». Я не мог заставить этот сайт компилироваться с оптимизацией * и * производить вывод. –

+0

Я вижу. Однако меня больше интересует более двусмысленный способ достижения этой переменной для переменной длины unsigned int. –

2

Если b - отрицательный, то вы можете просто сделать a + b.

В Руст, мы должны сначала привести один из операндов к тому же типу, что и другой, то мы должны использовать wrapping_add вместо того, чтобы просто с помощью оператора +, как отлаживать создает панику на переполнение (переполнение происходит при использовании + на usize потому что отрицательные числа становятся очень большими положительными числами после броска).

fn main() { 
    let a: usize = 5; 
    let b: isize = -2; 
    let c: usize = a.wrapping_add(b as usize); 
    println!("{}", c); // prints 3 
} 

С оптимизаций, wrapping_add компилирует к одной add инструкции.

Смежные вопросы